Threading and PInvoke

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 MSDN
Nov 2000
IDisposable and using

Idea for common cleanup
using(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



pointer types



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

Threading provides concurrent execution





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; }


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 lock
public 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



Monitor.Enter and Monitor.Exit



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

Cannot be used on value types: why not?
Threading model: Monitor

Methods

Monitor.Enter/Monitor.Exit


Monitor.Wait




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.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




Mutex and other synchronization



throws exception immediately
difficult to clean up: Why?
usually too draconian
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


useful constructions



as in Java
OS synchronization exposed
native ThreadPool
Really only need


lock
Monitor
P/Invoke

Use special attributes to make system calls



problems for C++


eg.
[DllImport(“kernel32”)]
static extern int GetProcessHeap();
calls to function in C library
name mangling: doesn’t match
General problem of COM/.NET interop

why does this matter?
COM Interoperability

Need metadata


Can then use COM class like .NET class




generated from TypeLib
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 Server
namespace 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



Can instantiate instance and call methods



ProgID / ClassID: looked up in registry
gives type of COM object
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-Bound
namespace 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 Example
namespace HelloWorld
{
using System;
class MyClass
{
[dllimport(“user32.dll”, CharSet=CharSet.Ansi)]
static extern int MessageBox(int h, string m,
string c, int t);
0);
}
}
public static int Main()
{
return MessageBox(0, "Hello World!", "Caption",
}
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
Unmanaged Code
Managed Code
DLL
.NET Application
DLL function
Call passes pointer to
callback function
Implementation of callback
function
Callback Example
public 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


contains, eg



__gc, __box, __typeof, __interface, __property
#pragma managed/unmanaged
Very useful for native access to C++ libraries


generates MSIL from C++
build a “managed wrapper”
Partial conversion to managed code