Threading and PInvoke Tom Roeder CS 215 2006

  • Slides: 33
Download presentation
Threading and P/Invoke Tom Roeder CS 215 2006 fa

Threading and P/Invoke Tom Roeder CS 215 2006 fa

Finalization l Recall C++ destructors: ~My. Class() { // cleanup } l l l

Finalization l Recall C++ destructors: ~My. Class() { // cleanup } l l l called when object is deleted does cleanup for this object Don’t do this in C# (or Java) l l l similar construct exists but only called on GC no guarantees when

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

Finalization l More common idiom: public void Finalize() { base. Finalize(); Dispose(false); } l l l maybe needed for unmanaged resources slows down GC significantly Finalization in GC: l when object with Finalize method created l l add to Finalization Queue when about to be GC’ed, add to Freachable Queue

Finalization images from MSDN Nov 2000

Finalization images from MSDN Nov 2000

IDisposable and using l Idea for common cleanup using(T t = new T()) {

IDisposable and using l Idea for common cleanup using(T t = new T()) { // do work with t } // t. Dispose is called by runtime l l IDispose provides one method: void Dispose() must provide finalizer, since must be called l l l when called from finalizer, don’t undo managed obj often add private void Dispose(bool) using calls Dispose automatically l used in class libraries, eg. for Socket

Weak References l Sometimes want to keep references but not cause the GC to

Weak References l Sometimes want to keep references but not cause the GC to wait l My. Class c = new My. Class(); Weak. Reference wr = new Weak. Reference(c); l Now c can be collected l wr will return null if referenced after c collected l but to truly access the object, we get a strong ref § l this is the Target property Why? l Useful for large objects l infrequently accessed l nice to have but can be regenerated

Resurrection l Imagine assigning this to global in finalizer l l object is now

Resurrection l Imagine assigning this to global in finalizer l l object is now reachable again! called “resurrection” if finalizer already called, access unpredictable Should not do this l l but, if do, may want to reject accesses in methods what would this finalize code do: some. Obj = this; System. GC. Register. For. Finalize()

System. GC l Can control the behavior of GC l l l not recommend

System. GC l Can control the behavior of GC l l l not recommend in general sometimes useful to give hints Some methods: l l Add/Remove. Memory. Pressure Re. Register. For/Suppress. Finalize Wait. For. Pending. Finalizers Collect

Memory Profiles l Good l l lots of small short-lived objects or few but

Memory Profiles l Good l l lots of small short-lived objects or few but long-lived ones few links between old and new objects Bad l l frequently create long-lived objects create many objects that live a long but fixed amount of time

unsafe mode l Sometimes need access to pointers l use unsafe modifier: unsafe public

unsafe mode l Sometimes need access to pointers l use unsafe modifier: unsafe public void Method(out int* pi) { int i = 10; fixed(int* pj = &i) { pi = pj; } } l l what is wrong with this method? unsafe modifier works a method modifier l or as a keyword for blocks

unsafe mode - Pointer details l Can only refer to “unmanaged” types l l

unsafe mode - Pointer details l Can only refer to “unmanaged” types l l l 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 l Cannot be executed in untrusted context l l l pointer types

unsafe mode l Cannot be executed in untrusted context l l l pointer types l l l security requirement: so can’t change memory eg. avoid stack smashing attacks cannot refer to a reference cannot refer to a struct that contains references int* pi, pj; // NOT int *pi, *pj;

Threading l Threading provides concurrent execution l l l Even useful on multiprocessor As

Threading l Threading provides concurrent execution l l l Even useful on multiprocessor As opposed to “sequential” execution Comes at cost of overhead Can be dangerous For example public int Increment(ref int x) { return ++x; } l l What happens when called by two threads? How to fix?

Threading l How to create a Thread l l l Create a new Thread

Threading l How to create a Thread l l l Create a new Thread instance with delegate Type: public delegate void Thread. Start(); Call Start method Let’s do an example on the board Thread will be scheduled when possible l l on SMP, may actually have many threads at once on UP, still may be useful when blocked l as in UI, networking code, dealing with drivers

Threading l Need synchronization primitives l l l Way to ensure that only one

Threading l Need synchronization primitives l l l Way to ensure that only one thread executes code in a region at once Called “critical section” C# provides (mostly in System. Threading) l l lock statement Monitor class Interrupt several others (see Birrell’s paper or MSDN)

Threading model: lock l Basic idea: each object has a lock public int Increment(ref

Threading model: lock l Basic idea: each object has a lock public int Increment(ref int x) {lock(this) return ++x; } l lock prevents more than one thread from entering forces sequential order What should we lock on? l l l 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 l Monitors provide synchronization construct l l l Monitor. Enter and

Threading model: Monitor l Monitors provide synchronization construct l l l Monitor. Enter and Monitor. Exit l l l entry waits on a queue waiting lets a new thread enter same semantics as the lock construct Why do we need both? Gets a lock on the object l Cannot be used on value types: why not?

Threading model: Monitor l Methods l Monitor. Enter/Monitor. Exit l l Monitor. Wait l

Threading model: Monitor l Methods l Monitor. Enter/Monitor. Exit l l Monitor. Wait l l enter/exit the monitor for a given object wait on a given object must be inside a monitor for that object signal-delayed semantics Monitor. Pulse/Monitor. Pulse. All l some thread(s) can be released to try the monitor

Threading model: Interrupt l Sometimes need to wake up a thread l l l

Threading model: Interrupt l Sometimes need to wake up a thread l l l eg. if UI cancelled eg. if event no longer needed Standard OO way: exceptions l Interrupt causes thread to throw Thread. Interrupted. Exception l l only on Wait or Sleep Allows cleanup of invariants

Other synchro classes l Abort l l Mutex and other synchronization l l l

Other synchro classes l Abort l l Mutex and other synchronization l l l throws exception immediately difficult to clean up: Why? usually too draconian good for interacting with Windows but stick with lock and Monitor, normally Reader. Writer Locks l not clear exactly what semantics they implement

Threading model: Thread. Pool l Instead of explicitly creating threads l l l create

Threading model: Thread. Pool l Instead of explicitly creating threads l l l create a pool pass delegates to worker threads enqueued in pool Queue. User. Work. Item l takes a Wait. Callback delegate Good for large amounts of parallel work l l l eg. N-Body problem automatically scales to number of processors “embarrasingly parallel” problems

Threading Conclusions l Standard monitor semantics l l useful constructions l l l as

Threading Conclusions l Standard monitor semantics l l useful constructions l l l as in Java OS synchronization exposed native Thread. Pool Really only need l l lock Monitor

P/Invoke l Use special attributes to make system calls l l l problems for

P/Invoke l Use special attributes to make system calls l l l problems for C++ l l eg. [Dll. Import(“kernel 32”)] static extern int Get. Process. Heap(); calls to function in C library name mangling: doesn’t match General problem of COM/. NET interop l why does this matter?

COM Interoperability l Need metadata l l Can then use COM class like. NET

COM Interoperability l Need metadata l l Can then use COM class like. NET class l l generated from Type. Lib even though major differences in models eg. threading, registration, inheritance useful for backwards compatibility Can bind early or late to class l either we know its type at compile time or not

Calling a COM Server namespace Calling. COMServer { using System; using COMServer. Lib; public

Calling a COM Server namespace Calling. COMServer { using System; using COMServer. Lib; public class Dot. NET_COMClient {. . . public static int Main(string[] args) { My. COMServer my. S = new My. COMServer(); return (my. S. Add (17, 4)); } } };

Late-Bound Activation l Use Reflection to get the type of the class l l

Late-Bound Activation l Use Reflection to get the type of the class l l l Can instantiate instance and call methods l l l Prog. ID / Class. ID: looked up in registry gives type of COM object uses Invoke. Method to call methods don’t have as strong type information here COM object wrapped by __Com. Object l can sometimes use as to get better info

Late-Bound namespace Late. Bound. Client { using System. Reflection; . . . Type typ;

Late-Bound namespace Late. Bound. Client { using System. Reflection; . . . Type typ; Object obj; Object[] prms = new Object[2]; int r; typ = Type. Get. Type. From. Prog. ID(„My. Lib. My. Server"); obj = Activator. Create. Instance(typ); prms[0] = 10; prms[1] = 150; r = (int)typ. Invoke. Member(„a. Method", Binding. Flags. Invoke. Method, null, obj, prms); . . . }

. NET from COM l l Needs to be public with public methods Need

. NET from COM l l Needs to be public with public methods Need to register a wrapper: use Reg. Asm tool l l provides Prog. ID/Class. ID information for registry necessary for COM integration Metadata must be converted to Type. Library Have same early- and late-bound activation l l early: by name late: by Prog. ID/Class. ID

Platform from. NET l l Calling static functions in DLLs P/Invoke provides services l

Platform from. NET l l Calling static functions in DLLs P/Invoke provides services l l l l Locates implementing DLL Loads DLL Finds function address l Fuzzy name matching algorithm Pushes arguments on stack Performs marshalling Enables pre-emptive garbage collection Transfers control to unmanaged code

P/Invoke Example namespace Hello. World { using System; class My. Class { [dllimport(“user 32.

P/Invoke Example namespace Hello. World { using System; class My. Class { [dllimport(“user 32. dll”, Char. Set=Char. Set. Ansi)] static extern int Message. Box(int h, string m, string c, int t); 0); } } public static int Main() { return Message. Box(0, "Hello World!", "Caption", }

P/Invoke Callbacks l Unmanaged code can call back to managed code l l l

P/Invoke Callbacks l Unmanaged code can call back to managed code l l l Unmanaged parameter is function pointer Must supply parameter as delegate P/Invoke creates callback thunk l Passes address of thunk as callback parameter Unmanaged Code Managed Code DLL . NET Application DLL function Call passes pointer to callback function Implementation of callback function

Callback Example public class Enum. Report { public bool Report(int hwnd, int l. Param)

Callback Example public class Enum. Report { public bool Report(int hwnd, int l. Param) { // report the window handle Console. Write("Window handle is "); Console. Write. Line(hwnd); return true; } }; public class Sample. Class { delegate bool Call. Back(int hwnd, int l. Param); [Dll. Import("user 32")] static extern int Enum. Windows(Call. Back x, int y); } public static void Main() { Enum. Report er = new Enum. Report(); Call. Back my. Call. Back = new Call. Back(er. Report); Enum. Windows(my. Call. Back, 0); }

Managed Extensions for C++ l Allows C++ code to be managed by GC/CLR l

Managed Extensions for C++ l Allows C++ code to be managed by GC/CLR l compile with /clr: It Just Works l l contains, eg l l l __gc, __box, __typeof, __interface, __property #pragma managed/unmanaged Very useful for native access to C++ libraries l l generates MSIL from C++ build a “managed wrapper” Partial conversion to managed code