// Copyright (c) 1997 by Bill Reck <breck@magna.com.au>
// This code may be used royalty-free as long as
// this notice appears in the product.
#include <windows.h>
#include <stdio.h>
#include "Handle.h"
#include "AddressRep.h"
class SyncRep {
public:
SyncRep() : count_(0)
{ ::InitializeCriticalSection(&sync_); }
~SyncRep() { ::DeleteCriticalSection(&sync_); }
void incrRefCount()
{ ::InterlockedIncrement(&count_); }
void decrRefCount()
{if (::InterlockedDecrement(&count_) <= 0) delete this;}
void acquireAccess() { ::EnterCriticalSection(&sync_); }
void releaseAccess() { ::LeaveCriticalSection(&sync_); }
private:
CRITICAL_SECTION sync_;
LONG count_;
};
template <class REP>
class Access {
public:
Access(REP *rep) : rep_(rep), acquired_(false) {}
Access(const Access<REP> &that)
: rep_(that.rep_), acquired_(false) {}
~Access() { if ( acquired_ ) rep_->releaseAccess(); }
REP *operator->() {
if (!acquired_)
{ rep_->acquireAccess(); acquired_ = true; }
return(rep_);
}
private:
REP *rep_;
bool acquired_;
};
template <class FUNCTOR, class ARG>
class Thread {
public:
static HANDLE start(ARG arg) {
DWORD notUsed;
ARG *freeStoreArg = new ARG(arg);
const HANDLE result =
::CreateThread(0, 0, base,
(void*)freeStoreArg, 0, ¬Used);
if (result == NULL) delete freeStoreArg;
return(result);
}
private:
static DWORD WINAPI base(void *threadArg) {
if (threadArg != 0) {
ARG *freeStoreArg = (ARG*)threadArg;
ARG stackArg = *freeStoreArg;
delete freeStoreArg;
FUNCTOR()(stackArg);
}
return(0);
}
};
template <class H> struct FaxFunctor {
void operator()(H a) const
{ if (!a.isNull()) a->fax(); }
};
void main(int argc, char *argv[]) {
// Define the address representation and handle types
typedef AddressRep< SyncRep > AddrRep;
typedef Handle< AddrRep, Access<AddrRep> > Address;
// A quick-n-dirty thread HANDLE collection
static const maxThreads = MAXIMUM_WAIT_OBJECTS;
HANDLE threadHandles[maxThreads];
unsigned threadCount = 0;
for (int i = 1; i < argc; ++i) {
// Create a new representation and handle
Address addr = new AddrRep;
// Reference a member of the representation
addr->firstName(argv[i]);
// Launch several threads for each address
for (int j = 0; j < 5 && threadCount < maxThreads; ++j)
threadHandles[threadCount++] =
Thread<
FaxFunctor<Address>, Address>::start(addr);
}
::printf("Waiting for the threads to finish...\n");
::WaitForMultipleObjects(
threadCount, threadHandles, true, INFINITE);
::printf("All done\n");
}
//End of File