Threading and P/Invoke Tom Roeder CS215 2006fa. Finalization Recall C++ destructors: ~MyClass() { //...
-
date post
21-Dec-2015 -
Category
Documents
-
view
218 -
download
2
Transcript of Threading and P/Invoke Tom Roeder CS215 2006fa. Finalization Recall C++ destructors: ~MyClass() { //...
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