// 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