00001 #pragma once
00002
00003 #include "../goodies.h"
00004
00005 namespace mongo {
00006
00022 #ifdef _WIN32
00023 typedef unsigned threadId_t;
00024 #else
00025 typedef pthread_t threadId_t;
00026 #endif
00027
00028
00029 #if defined(_DEBUG)
00030
00031 namespace race {
00032
00033 class CodePoint {
00034 public:
00035 string lastName;
00036 threadId_t lastTid;
00037 string file;
00038 CodePoint(string f) : lastTid(0), file(f) { }
00039 };
00040 class Check {
00041 public:
00042 Check(CodePoint& p) {
00043 threadId_t t = GetCurrentThreadId();
00044 if( p.lastTid == 0 ) {
00045 p.lastTid = t;
00046 p.lastName = getThreadName();
00047 }
00048 else if( t != p.lastTid ) {
00049 log() << "\n\n\n\n\nRACE? error assert\n " << p.file << '\n'
00050 << " " << p.lastName
00051 << " " << getThreadName() << "\n\n" << endl;
00052 mongoAbort("racecheck");
00053 }
00054 };
00055 };
00056
00057 }
00058
00059 #define RACECHECK
00060
00061
00062
00063
00064
00065 class CodeBlock {
00066 volatile int n;
00067 threadId_t tid;
00068 void fail() {
00069 log() << "synchronization (race condition) failure" << endl;
00070 printStackTrace();
00071 ::abort();
00072 }
00073 void enter() {
00074 if( ++n != 1 ) fail();
00075 #if defined(_WIN32)
00076 tid = GetCurrentThreadId();
00077 #endif
00078 }
00079 void leave() {
00080 if( --n != 0 ) fail();
00081 }
00082 public:
00083 CodeBlock() : n(0) { }
00084
00085 class Within {
00086 CodeBlock& _s;
00087 public:
00088 Within(CodeBlock& s) : _s(s) { _s.enter(); }
00089 ~Within() { _s.leave(); }
00090 };
00091
00092 void assertWithin() {
00093 assert( n == 1 );
00094 #if defined(_WIN32)
00095 assert( GetCurrentThreadId() == tid );
00096 #endif
00097 }
00098 };
00099
00100 #else
00101
00102 #define RACECHECK
00103
00104 class CodeBlock{
00105 public:
00106 class Within {
00107 public:
00108 Within(CodeBlock&) { }
00109 };
00110 void assertWithin() { }
00111 };
00112
00113 #endif
00114
00115 }