threading and p/invoke tom roeder cs215 2006fa. finalization recall c++ destructors: ~myclass() { //...

Post on 21-Dec-2015

218 Views

Category:

Documents

2 Downloads

Preview:

Click to see full reader

TRANSCRIPT

Threading and P/Invoke

Tom Roeder

CS215 2006fa

Finalization

Recall C++ destructors:~MyClass() { // cleanup}

called when object is deleted does cleanup for this object

Don’t do this in C# (or Java) similar construct exists but only called on GC no guarantees when

Finalization

More common idiom:public void Finalize() { base.Finalize(); Dispose(false);}

maybe needed for unmanaged resources slows down GC significantly

Finalization in GC: when object with Finalize method created

add to Finalization Queue when about to be GC’ed, add to Freachable Queue

Finalization

images from MSDNNov 2000

IDisposable and using

Idea for common cleanupusing(T t = new T()) { // do work with t} // t.Dispose is called by runtime

IDispose provides one method: void Dispose() must provide finalizer, since must be called

when called from finalizer, don’t undo managed obj often add private void Dispose(bool)

using calls Dispose automatically used in class libraries, eg. for Socket

Weak References

Sometimes want to keep references but not cause the GC to wait MyClass c = new MyClass();

WeakReference wr = new WeakReference(c);

Now c can be collected wr will return null if referenced after c collected but to truly access the object, we get a strong ref

this is the Target property

Why? Useful for large objects

infrequently accessed nice to have but can be regenerated

Resurrection

Imagine assigning this to global in finalizer object is now reachable again! called “resurrection” if finalizer already called, access unpredictable

Should not do this but, if do, may want to reject accesses in methods what would this finalize code do:

someObj = this;System.GC.ReRegisterForFinalize()

System.GC

Can control the behavior of GC not recommend in general sometimes useful to give hints

Some methods: Add/RemoveMemoryPressure ReRegisterFor/SuppressFinalize WaitForPendingFinalizers Collect

Memory Profiles

Good lots of small short-lived objects or few but long-lived ones few links between old and new objects

Bad frequently create long-lived objects create many objects that live a long but fixed

amount of time

unsafe mode

Sometimes need access to pointers use unsafe modifier:

unsafe public void Method(out int* pi) { int i = 10; fixed(int* pj = &i) { pi = pj; }}

what is wrong with this method? unsafe modifier works a method modifier

or as a keyword for blocks

unsafe mode - Pointer details

Can only refer to “unmanaged” types or enums or structs composed of unmanaged types

Not a subclass of object void* exists, but no arithmetic allowed boxing/unboxing does not work stackalloc gets memory from the stack

unsafe mode

Cannot be executed in untrusted context security requirement: so can’t change memory eg. avoid stack smashing attacks

pointer types cannot refer to a reference cannot refer to a struct that contains references

int* pi, pj; // NOT int *pi, *pj;

Threading

Threading provides concurrent execution Even useful on multiprocessor As opposed to “sequential” execution Comes at cost of overhead Can be dangerous

For examplepublic int Increment(ref int x) { return ++x; }

What happens when called by two threads? How to fix?

Threading

How to create a Thread Create a new Thread instance with delegate Type: public delegate void ThreadStart(); Call Start method Let’s do an example on the board

Thread will be scheduled when possible on SMP, may actually have many threads at once on UP, still may be useful when blocked

as in UI, networking code, dealing with drivers

Threading

Need synchronization primitives Way to ensure that only one thread executes

code in a region at once Called “critical section”

C# provides (mostly in System.Threading) lock statement Monitor class Interrupt several others (see Birrell’s paper or MSDN)

Threading model: lock

Basic idea: each object has a lockpublic int Increment(ref int x) {lock(this) return ++x;}

lock prevents more than one thread from entering forces sequential order

What should we lock on? for instance variables: this for globals and statics: typeof(container) something that will be same for all threads that

access this shared memory

Threading model: Monitor

Monitors provide synchronization construct entry waits on a queue waiting lets a new thread enter

Monitor.Enter and Monitor.Exit same semantics as the lock construct Why do we need both?

Gets a lock on the object Cannot be used on value types: why not?

Threading model: Monitor

Methods Monitor.Enter/Monitor.Exit

enter/exit the monitor for a given object Monitor.Wait

wait on a given object must be inside a monitor for that object signal-delayed semantics

Monitor.Pulse/Monitor.PulseAll some thread(s) can be released to try the monitor

Threading model: Interrupt

Sometimes need to wake up a thread eg. if UI cancelled eg. if event no longer needed

Standard OO way: exceptions Interrupt causes thread to throw

ThreadInterruptedException only on Wait or Sleep

Allows cleanup of invariants

Other synchro classes

Abort throws exception immediately difficult to clean up: Why? usually too draconian

Mutex and other synchronization good for interacting with Windows but stick with lock and Monitor, normally

ReaderWriter Locks not clear exactly what semantics they implement

Threading model: ThreadPool

Instead of explicitly creating threads create a pool pass delegates to worker threads enqueued in pool QueueUserWorkItem

takes a WaitCallback delegate

Good for large amounts of parallel work eg. N-Body problem automatically scales to number of processors “embarrasingly parallel” problems

Threading Conclusions

Standard monitor semantics as in Java

useful constructions OS synchronization exposed native ThreadPool

Really only need lock Monitor

P/Invoke

Use special attributes to make system calls eg.

[DllImport(“kernel32”)]static extern int GetProcessHeap();

calls to function in C library problems for C++

name mangling: doesn’t match General problem of COM/.NET interop

why does this matter?

COM Interoperability

Need metadata generated from TypeLib

Can then use COM class like .NET class even though major differences in models eg. threading, registration, inheritance useful for backwards compatibility

Can bind early or late to class either we know its type at compile time or not

Calling a COM Servernamespace CallingCOMServer{

using System;using COMServerLib;

public class DotNET_COMClient{...

public static int Main(string[] args){

MyCOMServer myS = new MyCOMServer();return (myS.Add (17,4));

}}

};

Late-Bound Activation

Use Reflection to get the type of the class ProgID / ClassID: looked up in registry gives type of COM object

Can instantiate instance and call methods uses InvokeMethod to call methods don’t have as strong type information here

COM object wrapped by __ComObject can sometimes use as to get better info

Late-Boundnamespace LateBoundClient{

using System.Reflection;...Type typ;Object obj;Object[] prms = new Object[2];int r;typ = Type.GetTypeFromProgID(„MyLib.MyServer");obj = Activator.CreateInstance(typ);prms[0] = 10; prms[1] = 150; r = (int)typ.InvokeMember(„aMethod",

BindingFlags.InvokeMethod, null, obj, prms);...

}

.NET from COM

Needs to be public with public methods Need to register a wrapper: use RegAsm tool

provides ProgID/ClassID information for registry necessary for COM integration

Metadata must be converted to TypeLibrary Have same early- and late-bound activation

early: by name late: by ProgID/ClassID

Platform from .NET

Calling static functions in DLLs P/Invoke provides services

Locates implementing DLL Loads DLL Finds function address

Fuzzy name matching algorithm Pushes arguments on stack Performs marshalling Enables pre-emptive garbage collection Transfers control to unmanaged code

P/Invoke Examplenamespace HelloWorld

{ using System;

class MyClass { [dllimport(“user32.dll”, CharSet=CharSet.Ansi)] static extern int MessageBox(int h, string m,

string c, int t); public static int Main() { return MessageBox(0, "Hello World!", "Caption", 0); } }}

P/Invoke Callbacks

Unmanaged code can call back to managed code Unmanaged parameter is function pointer Must supply parameter as delegate P/Invoke creates callback thunk

Passes address of thunk as callback parameter

Managed Code

.NET Application

Call passes pointer to callback function

Implementation of callback function

Unmanaged Code

DLL

DLL function

Callback Examplepublic class EnumReport

{ public bool Report(int hwnd, int lParam) { // report the window handle Console.Write("Window handle is "); Console.WriteLine(hwnd); return true; }};public class SampleClass{ delegate bool CallBack(int hwnd, int lParam);

[DllImport("user32")] static extern int EnumWindows(CallBack x, int y);

public static void Main() { EnumReport er = new EnumReport(); CallBack myCallBack = new CallBack(er.Report); EnumWindows(myCallBack, 0); }}

Managed Extensions for C++

Allows C++ code to be managed by GC/CLR compile with /clr: It Just Works

generates MSIL from C++ contains, eg

__gc, __box, __typeof, __interface, __property #pragma managed/unmanaged

Very useful for native access to C++ libraries build a “managed wrapper”

Partial conversion to managed code

top related