Thread threads[MAX_THREADS];
SplitPoint SplitPointStack[MAX_THREADS][ACTIVE_SPLIT_POINTS_MAX];
- Lock MPLock;
+ Lock MPLock, WaitLock;
#if !defined(_MSC_VER)
pthread_cond_t WaitCond;
- pthread_mutex_t WaitLock;
#else
HANDLE SitIdleEvent[MAX_THREADS];
#endif
const Depth RazorDepth = 4 * OnePly;
// Dynamic razoring margin based on depth
- inline Value razor_margin(Depth d) { return Value(0x200 + 0x10 * d); }
+ inline Value razor_margin(Depth d) { return Value(0x200 + 0x10 * int(d)); }
// Step 8. Null move search with verification search
const Depth IIDDepthAtPVNodes = 5 * OnePly;
const Depth IIDDepthAtNonPVNodes = 8 * OnePly;
- // Internal iterative deepening margin. At Non-PV nodes
- // we do an internal iterative deepening
- // search when the static evaluation is at most IIDMargin below beta.
+ // At Non-PV nodes we do an internal iterative deepening search
+ // when the static evaluation is at most IIDMargin below beta.
const Value IIDMargin = Value(0x100);
// Step 11. Decide the new search depth
- // Extensions. Configurable UCI options.
+ // Extensions. Configurable UCI options
// Array index 0 is used at non-PV nodes, index 1 at PV nodes.
Depth CheckExtension[2], SingleEvasionExtension[2], PawnPushTo7thExtension[2];
Depth PassedPawnExtension[2], PawnEndgameExtension[2], MateThreatExtension[2];
const Value FutilityMarginQS = Value(0x80);
// Futility lookup tables (initialized at startup) and their getter functions
- int32_t FutilityMarginsMatrix[14][64]; // [depth][moveNumber]
+ int32_t FutilityMarginsMatrix[16][64]; // [depth][moveNumber]
int FutilityMoveCountArray[32]; // [depth]
- inline Value futility_margin(Depth d, int mn) { return Value(d < 7*OnePly ? FutilityMarginsMatrix[Max(d, 0)][Min(mn, 63)] : 2 * VALUE_INFINITE); }
- inline int futility_move_count(Depth d) { return d < 16*OnePly ? FutilityMoveCountArray[d] : 512; }
+ inline Value futility_margin(Depth d, int mn) { return Value(d < 7 * OnePly ? FutilityMarginsMatrix[Max(d, 0)][Min(mn, 63)] : 2 * VALUE_INFINITE); }
+ inline int futility_move_count(Depth d) { return d < 16 * OnePly ? FutilityMoveCountArray[d] : 512; }
// Step 14. Reduced search
inline Depth pv_reduction(Depth d, int mn) { return (Depth) PVReductionMatrix[Min(d / 2, 63)][Min(mn, 63)]; }
inline Depth nonpv_reduction(Depth d, int mn) { return (Depth) NonPVReductionMatrix[Min(d / 2, 63)][Min(mn, 63)]; }
- // Step. Common adjustments
+ // Common adjustments
// Search depth at iteration 1
const Depth InitialDepth = OnePly;
/// Global variables
- // Iteration counters
+ // Iteration counter
int Iteration;
// Scores and number of times the best move changed for each iteration
int MultiPV;
// Time managment variables
- int RootMoveNumber;
- int SearchStartTime;
- int MaxNodes, MaxDepth;
+ int RootMoveNumber, SearchStartTime, MaxNodes, MaxDepth;
int MaxSearchTime, AbsoluteMaxSearchTime, ExtraSearchTime, ExactMaxTime;
bool UseTimeManagement, InfiniteSearch, PonderSearch, StopOnPonderhit;
- bool AbortSearch, Quit;
- bool AspirationFailLow;
+ bool AbortSearch, Quit, AspirationFailLow;
// Show current line?
bool ShowCurrentLine;
bool UseLogFile;
std::ofstream LogFile;
- // MP related variables
+ // Multi-threads related variables
Depth MinimumSplitDepth;
int MaxThreadsPerSplitPoint;
ThreadsManager TM;
- // Node counters, used only by thread[0] but try to keep in different
- // cache lines (64 bytes each) from the heavy SMP read accessed variables.
+ // Node counters, used only by thread[0] but try to keep in different cache
+ // lines (64 bytes each) from the heavy multi-thread read accessed variables.
int NodesSincePoll;
int NodesBetweenPolls = 30000;
// History table
History H;
- /// Functions
+ /// Local functions
Value id_loop(const Position& pos, Move searchMoves[]);
Value root_search(Position& pos, SearchStack ss[], RootMoveList& rml, Value& oldAlpha, Value& beta);
void ponderhit();
void wait_for_stop_or_ponderhit();
void init_ss_array(SearchStack ss[]);
+ void print_pv_info(const Position& pos, SearchStack ss[], Value alpha, Value beta, Value value);
#if !defined(_MSC_VER)
void *init_thread(void *threadID);
int perft(Position& pos, Depth depth)
{
+ StateInfo st;
Move move;
int sum = 0;
- MovePicker mp = MovePicker(pos, MOVE_NONE, depth, H);
+ MovePicker mp(pos, MOVE_NONE, depth, H);
// If we are at the last ply we don't need to do and undo
// the moves, just to count them.
CheckInfo ci(pos);
while ((move = mp.get_next_move()) != MOVE_NONE)
{
- StateInfo st;
pos.do_move(move, st, ci, pos.move_is_check(move, ci));
sum += perft(pos, depth - OnePly);
pos.undo_move(move);
int maxNodes, int maxTime, Move searchMoves[]) {
// Initialize global search variables
- StopOnPonderhit = AbortSearch = Quit = false;
- AspirationFailLow = false;
+ StopOnPonderhit = AbortSearch = Quit = AspirationFailLow = false;
NodesSincePoll = 0;
+ TM.resetNodeCounters();
SearchStartTime = get_system_time();
ExactMaxTime = maxTime;
MaxDepth = maxDepth;
// Look for a book move, only during games, not tests
if (UseTimeManagement && get_option_value_bool("OwnBook"))
{
- Move bookMove;
if (get_option_value_string("Book File") != OpeningBook.file_name())
OpeningBook.open(get_option_value_string("Book File"));
- bookMove = OpeningBook.get_move(pos);
+ Move bookMove = OpeningBook.get_move(pos);
if (bookMove != MOVE_NONE)
{
if (PonderSearch)
}
}
- TM.resetNodeCounters();
-
+ // Reset loseOnTime flag at the beginning of a new game
if (button_was_pressed("New Game"))
- loseOnTime = false; // Reset at the beginning of a new game
+ loseOnTime = false;
// Read UCI option values
TT.set_size(get_option_value_int("Hash"));
if (button_was_pressed("Clear Hash"))
TT.clear();
- bool PonderingEnabled = get_option_value_bool("Ponder");
- MultiPV = get_option_value_int("MultiPV");
-
- CheckExtension[1] = Depth(get_option_value_int("Check Extension (PV nodes)"));
- CheckExtension[0] = Depth(get_option_value_int("Check Extension (non-PV nodes)"));
-
+ CheckExtension[1] = Depth(get_option_value_int("Check Extension (PV nodes)"));
+ CheckExtension[0] = Depth(get_option_value_int("Check Extension (non-PV nodes)"));
SingleEvasionExtension[1] = Depth(get_option_value_int("Single Evasion Extension (PV nodes)"));
SingleEvasionExtension[0] = Depth(get_option_value_int("Single Evasion Extension (non-PV nodes)"));
-
PawnPushTo7thExtension[1] = Depth(get_option_value_int("Pawn Push to 7th Extension (PV nodes)"));
PawnPushTo7thExtension[0] = Depth(get_option_value_int("Pawn Push to 7th Extension (non-PV nodes)"));
+ PassedPawnExtension[1] = Depth(get_option_value_int("Passed Pawn Extension (PV nodes)"));
+ PassedPawnExtension[0] = Depth(get_option_value_int("Passed Pawn Extension (non-PV nodes)"));
+ PawnEndgameExtension[1] = Depth(get_option_value_int("Pawn Endgame Extension (PV nodes)"));
+ PawnEndgameExtension[0] = Depth(get_option_value_int("Pawn Endgame Extension (non-PV nodes)"));
+ MateThreatExtension[1] = Depth(get_option_value_int("Mate Threat Extension (PV nodes)"));
+ MateThreatExtension[0] = Depth(get_option_value_int("Mate Threat Extension (non-PV nodes)"));
+
+ MinimumSplitDepth = get_option_value_int("Minimum Split Depth") * OnePly;
+ MaxThreadsPerSplitPoint = get_option_value_int("Maximum Number of Threads per Split Point");
+ ShowCurrentLine = get_option_value_bool("UCI_ShowCurrLine");
+ MultiPV = get_option_value_int("MultiPV");
+ Chess960 = get_option_value_bool("UCI_Chess960");
+ UseLogFile = get_option_value_bool("Use Search Log");
- PassedPawnExtension[1] = Depth(get_option_value_int("Passed Pawn Extension (PV nodes)"));
- PassedPawnExtension[0] = Depth(get_option_value_int("Passed Pawn Extension (non-PV nodes)"));
-
- PawnEndgameExtension[1] = Depth(get_option_value_int("Pawn Endgame Extension (PV nodes)"));
- PawnEndgameExtension[0] = Depth(get_option_value_int("Pawn Endgame Extension (non-PV nodes)"));
-
- MateThreatExtension[1] = Depth(get_option_value_int("Mate Threat Extension (PV nodes)"));
- MateThreatExtension[0] = Depth(get_option_value_int("Mate Threat Extension (non-PV nodes)"));
-
- Chess960 = get_option_value_bool("UCI_Chess960");
- ShowCurrentLine = get_option_value_bool("UCI_ShowCurrLine");
- UseLogFile = get_option_value_bool("Use Search Log");
if (UseLogFile)
LogFile.open(get_option_value_string("Search Log Filename").c_str(), std::ios::out | std::ios::app);
- MinimumSplitDepth = get_option_value_int("Minimum Split Depth") * OnePly;
- MaxThreadsPerSplitPoint = get_option_value_int("Maximum Number of Threads per Split Point");
-
read_weights(pos.side_to_move());
// Set the number of active threads
}
}
- if (PonderingEnabled)
+ if (get_option_value_bool("Ponder"))
{
MaxSearchTime += MaxSearchTime / 4;
MaxSearchTime = Min(MaxSearchTime, AbsoluteMaxSearchTime);
}
}
- // Set best NodesBetweenPolls interval
+ // Set best NodesBetweenPolls interval to avoid lagging under
+ // heavy time pressure.
if (MaxNodes)
NodesBetweenPolls = Min(MaxNodes, 30000);
else if (myTime && myTime < 1000)
else
NodesBetweenPolls = 30000;
- // Write information to search log file
+ // Write search information to log file
if (UseLogFile)
LogFile << "Searching: " << pos.to_fen() << endl
<< "infinite: " << infinite
<< " increment: " << myIncrement
<< " moves to go: " << movesToGo << endl;
- // LSN filtering. Used only for developing purpose. Disabled by default.
+ // LSN filtering. Used only for developing purposes, disabled by default
if ( UseLSNFiltering
&& loseOnTime)
{
}
// Init futility margins array
- for (int i = 0; i < 14; i++) // i == depth (OnePly = 2)
+ for (int i = 0; i < 16; i++) // i == depth (OnePly = 2)
for (int j = 0; j < 64; j++) // j == moveNumber
{
- FutilityMarginsMatrix[i][j] = (i < 2 ? 0 : 112 * bitScanReverse32(i * i / 2)) - 8 * j; // FIXME: test using log instead of BSR
+ // FIXME: test using log instead of BSR
+ FutilityMarginsMatrix[i][j] = (i < 2 ? 0 : 112 * bitScanReverse32(i * i / 2)) - 8 * j;
}
// Init futility move count array
Position p(pos);
SearchStack ss[PLY_MAX_PLUS_2];
+ Move EasyMove = MOVE_NONE;
+ Value value, alpha = -VALUE_INFINITE, beta = VALUE_INFINITE;
- // searchMoves are verified, copied, scored and sorted
+ // Moves to search are verified, copied, scored and sorted
RootMoveList rml(p, searchMoves);
// Handle special case of searching on a mate/stale position
if (PonderSearch)
wait_for_stop_or_ponderhit();
- return pos.is_check()? -VALUE_MATE : VALUE_DRAW;
+ return pos.is_check() ? -VALUE_MATE : VALUE_DRAW;
}
- // Print RootMoveList c'tor startup scoring to the standard output,
- // so that we print information also for iteration 1.
- cout << "info depth " << 1 << "\ninfo depth " << 1
+ // Print RootMoveList startup scoring to the standard output,
+ // so to output information also for iteration 1.
+ cout << "info depth " << 1
+ << "\ninfo depth " << 1
<< " score " << value_to_string(rml.get_move_score(0))
<< " time " << current_search_time()
<< " nodes " << TM.nodes_searched()
Iteration = 1;
// Is one move significantly better than others after initial scoring ?
- Move EasyMove = MOVE_NONE;
if ( rml.move_count() == 1
|| rml.get_move_score(0) > rml.get_move_score(1) + EasyMoveMargin)
EasyMove = rml.get_move(0);
while (Iteration < PLY_MAX)
{
// Initialize iteration
- rml.sort();
Iteration++;
BestMoveChangesByIteration[Iteration] = 0;
if (Iteration <= 5)
cout << "info depth " << Iteration << endl;
- // Calculate dynamic search window based on previous iterations
- Value alpha, beta;
-
+ // Calculate dynamic aspiration window based on previous iterations
if (MultiPV == 1 && Iteration >= 6 && abs(ValueByIteration[Iteration - 1]) < VALUE_KNOWN_WIN)
{
int prevDelta1 = ValueByIteration[Iteration - 1] - ValueByIteration[Iteration - 2];
alpha = Max(ValueByIteration[Iteration - 1] - AspirationDelta, -VALUE_INFINITE);
beta = Min(ValueByIteration[Iteration - 1] + AspirationDelta, VALUE_INFINITE);
}
- else
- {
- alpha = - VALUE_INFINITE;
- beta = VALUE_INFINITE;
- }
- // Search to the current depth
- Value value = root_search(p, ss, rml, alpha, beta);
+ // Search to the current depth, rml is updated and sorted
+ value = root_search(p, ss, rml, alpha, beta);
// Write PV to transposition table, in case the relevant entries have
// been overwritten during the search.
//Save info about search result
ValueByIteration[Iteration] = value;
- // Drop the easy move if it differs from the new best move
+ // Drop the easy move if differs from the new best move
if (ss[0].pv[0] != EasyMove)
EasyMove = MOVE_NONE;
&& abs(ValueByIteration[Iteration-1]) >= abs(VALUE_MATE) - 100)
stopSearch = true;
- // Stop search early if one move seems to be much better than the rest
+ // Stop search early if one move seems to be much better than the others
int64_t nodes = TM.nodes_searched();
if ( Iteration >= 8
&& EasyMove == ss[0].pv[0]
if (stopSearch)
{
- if (!PonderSearch)
- break;
- else
+ if (PonderSearch)
StopOnPonderhit = true;
+ else
+ break;
}
}
break;
}
- rml.sort();
-
// If we are pondering or in infinite search, we shouldn't print the
// best move before we are told to do so.
if (!AbortSearch && (PonderSearch || InfiniteSearch))
ss[0].pv[0] = rml.get_move(0);
ss[0].pv[1] = MOVE_NONE;
}
+
+ assert(ss[0].pv[0] != MOVE_NONE);
+
cout << "bestmove " << ss[0].pv[0];
+
if (ss[0].pv[1] != MOVE_NONE)
cout << " ponder " << ss[0].pv[1];
StateInfo st;
p.do_move(ss[0].pv[0], st);
- LogFile << "\nPonder move: " << move_to_san(p, ss[0].pv[1]) << endl;
+ LogFile << "\nPonder move: "
+ << move_to_san(p, ss[0].pv[1]) // Works also with MOVE_NONE
+ << endl;
}
return rml.get_move_score(0);
}
// root_search() is the function which searches the root node. It is
// similar to search_pv except that it uses a different move ordering
- // scheme and prints some information to the standard output.
+ // scheme, prints some information to the standard output and handles
+ // the fail low/high loops.
Value root_search(Position& pos, SearchStack ss[], RootMoveList& rml, Value& oldAlpha, Value& beta) {
+ EvalInfo ei;
+ StateInfo st;
int64_t nodes;
Move move;
- StateInfo st;
Depth depth, ext, newDepth;
- Value value;
- CheckInfo ci(pos);
+ Value value, alpha;
+ bool isCheck, moveIsCheck, captureOrPromotion, dangerous;
int researchCount = 0;
- bool moveIsCheck, captureOrPromotion, dangerous;
- Value alpha = oldAlpha;
- bool isCheck = pos.is_check();
+ CheckInfo ci(pos);
+ alpha = oldAlpha;
+ isCheck = pos.is_check();
// Evaluate the position statically
- EvalInfo ei;
ss[0].eval = !isCheck ? evaluate(pos, ei, 0) : VALUE_NONE;
while (1) // Fail low loop
{
+ // Sort the moves before to (re)search
+ rml.sort();
// Loop through all the moves in the root move list
for (int i = 0; i < rml.move_count() && !AbortSearch; i++)
continue;
}
+ // This is used by time management and starts from 1
RootMoveNumber = i + 1;
// Save the current node count before the move is searched
ext = extension(pos, move, true, captureOrPromotion, moveIsCheck, false, false, &dangerous);
newDepth = depth + ext;
+ // Reset value before the search
value = - VALUE_INFINITE;
while (1) // Fail high loop
{
-
// Make the move, and search it
pos.do_move(move, st, ci, moveIsCheck);
if (MultiPV > 1)
alpha = -VALUE_INFINITE;
+ // Full depth PV search, done on first move or after a fail high
value = -search_pv(pos, ss, -beta, -alpha, newDepth, 1, 0);
}
else
// if the move fails high will be re-searched at full depth.
bool doFullDepthSearch = true;
- if ( depth >= 3*OnePly // FIXME was newDepth
+ if ( depth >= 3 * OnePly // FIXME was newDepth
&& !dangerous
&& !captureOrPromotion
&& !move_is_castle(move))
{
- ss[0].reduction = pv_reduction(depth, RootMoveNumber - MultiPV + 1);
+ ss[0].reduction = pv_reduction(depth, i - MultiPV + 2);
if (ss[0].reduction)
{
+ // Reduced depth non-pv search using alpha as upperbound
value = -search(pos, ss, -alpha, newDepth-ss[0].reduction, 1, true, 0);
doFullDepthSearch = (value > alpha);
}
if (doFullDepthSearch)
{
+ // Full depth non-pv search using alpha as upperbound
ss[0].reduction = Depth(0);
value = -search(pos, ss, -alpha, newDepth, 1, true, 0);
+ // If we are above alpha then research at same depth but as PV
+ // to get a correct score or eventually a fail high above beta.
if (value > alpha)
value = -search_pv(pos, ss, -beta, -alpha, newDepth, 1, 0);
}
if (AbortSearch || value < beta)
break;
- // We are failing high and going to do a research. It's important to update score
- // before research in case we run out of time while researching.
+ // We are failing high and going to do a research. It's important to update
+ // the score before research in case we run out of time while researching.
rml.set_move_score(i, value);
update_pv(ss, 0);
TT.extract_pv(pos, ss[0].pv, PLY_MAX);
rml.set_move_pv(i, ss[0].pv);
- // Print search information to the standard output
- cout << "info depth " << Iteration
- << " score " << value_to_string(value)
- << ((value >= beta) ? " lowerbound" :
- ((value <= alpha)? " upperbound" : ""))
- << " time " << current_search_time()
- << " nodes " << TM.nodes_searched()
- << " nps " << nps()
- << " pv ";
-
- for (int j = 0; ss[0].pv[j] != MOVE_NONE && j < PLY_MAX; j++)
- cout << ss[0].pv[j] << " ";
-
- cout << endl;
-
- if (UseLogFile)
- {
- ValueType type = (value >= beta ? VALUE_TYPE_LOWER
- : (value <= alpha ? VALUE_TYPE_UPPER : VALUE_TYPE_EXACT));
-
- LogFile << pretty_pv(pos, current_search_time(), Iteration,
- TM.nodes_searched(), value, type, ss[0].pv) << endl;
- }
+ // Print information to the standard output
+ print_pv_info(pos, ss, alpha, beta, value);
// Prepare for a research after a fail high, each time with a wider window
researchCount++;
break;
// Remember beta-cutoff and searched nodes counts for this move. The
- // info is used to sort the root moves at the next iteration.
+ // info is used to sort the root moves for the next iteration.
int64_t our, their;
TM.get_beta_counters(pos.side_to_move(), our, their);
rml.set_beta_counters(i, our, their);
if (i > 0)
BestMoveChangesByIteration[Iteration]++;
- // Print search information to the standard output
- cout << "info depth " << Iteration
- << " score " << value_to_string(value)
- << ((value >= beta) ? " lowerbound" :
- ((value <= alpha)? " upperbound" : ""))
- << " time " << current_search_time()
- << " nodes " << TM.nodes_searched()
- << " nps " << nps()
- << " pv ";
-
- for (int j = 0; ss[0].pv[j] != MOVE_NONE && j < PLY_MAX; j++)
- cout << ss[0].pv[j] << " ";
+ // Print information to the standard output
+ print_pv_info(pos, ss, alpha, beta, value);
- cout << endl;
-
- if (UseLogFile)
- {
- ValueType type = (value >= beta ? VALUE_TYPE_LOWER
- : (value <= alpha ? VALUE_TYPE_UPPER : VALUE_TYPE_EXACT));
-
- LogFile << pretty_pv(pos, current_search_time(), Iteration,
- TM.nodes_searched(), value, type, ss[0].pv) << endl;
- }
+ // Raise alpha to setup proper non-pv search upper bound, note
+ // that we can end up with alpha >= beta and so get a fail high.
if (value > alpha)
alpha = value;
}
{
cout << "info multipv " << j + 1
<< " score " << value_to_string(rml.get_move_score(j))
- << " depth " << ((j <= i)? Iteration : Iteration - 1)
+ << " depth " << (j <= i ? Iteration : Iteration - 1)
<< " time " << current_search_time()
<< " nodes " << TM.nodes_searched()
<< " nps " << nps()
cout << endl;
}
- alpha = rml.get_move_score(Min(i, MultiPV-1));
+ alpha = rml.get_move_score(Min(i, MultiPV - 1));
}
} // PV move or new best move
} // Fail low loop
+ // Sort the moves before to return
+ rml.sort();
+
return alpha;
}
// if the move fails high will be re-searched at full depth.
bool doFullDepthSearch = true;
- if ( depth >= 3*OnePly
+ if ( depth >= 3 * OnePly
&& !dangerous
&& !captureOrPromotion
&& !move_is_castle(move)
// Loop through all legal moves until no moves remain or a beta cutoff occurs
// Initialize a MovePicker object for the current position
- MovePicker mp = MovePicker(pos, ttMove, depth, H, &ss[ply]);
+ MovePicker mp = MovePicker(pos, ttMove, depth, H, &ss[ply], beta);
CheckInfo ci(pos);
while ( bestValue < beta
}
+ // print_pv_info() prints to standard output and eventually to log file information on
+ // the current PV line. It is called at each iteration or after a new pv is found.
+
+ void print_pv_info(const Position& pos, SearchStack ss[], Value alpha, Value beta, Value value) {
+
+ cout << "info depth " << Iteration
+ << " score " << value_to_string(value)
+ << ((value >= beta) ? " lowerbound" :
+ ((value <= alpha)? " upperbound" : ""))
+ << " time " << current_search_time()
+ << " nodes " << TM.nodes_searched()
+ << " nps " << nps()
+ << " pv ";
+
+ for (int j = 0; ss[0].pv[j] != MOVE_NONE && j < PLY_MAX; j++)
+ cout << ss[0].pv[j] << " ";
+
+ cout << endl;
+
+ if (UseLogFile)
+ {
+ ValueType type = (value >= beta ? VALUE_TYPE_LOWER
+ : (value <= alpha ? VALUE_TYPE_UPPER : VALUE_TYPE_EXACT));
+
+ LogFile << pretty_pv(pos, current_search_time(), Iteration,
+ TM.nodes_searched(), value, type, ss[0].pv) << endl;
+ }
+ }
+
+
// init_thread() is the function which is called when a new thread is
// launched. It simply calls the idle_loop() function with the supplied
// threadID. There are two versions of this function; one for POSIX
DWORD WINAPI init_thread(LPVOID threadID) {
TM.idle_loop(*(int*)threadID, NULL);
- return NULL;
+ return 0;
}
#endif
threads[threadID].state = THREAD_SLEEPING;
#if !defined(_MSC_VER)
- pthread_mutex_lock(&WaitLock);
+ lock_grab(&WaitLock);
if (AllThreadsShouldSleep || threadID >= ActiveThreads)
pthread_cond_wait(&WaitCond, &WaitLock);
- pthread_mutex_unlock(&WaitLock);
+ lock_release(&WaitLock);
#else
WaitForSingleObject(SitIdleEvent[threadID], INFINITE);
#endif
// Initialize global locks
lock_init(&MPLock, NULL);
+ lock_init(&WaitLock, NULL);
+
+#if !defined(_MSC_VER)
+ pthread_cond_init(&WaitCond, NULL);
+#else
+ for (i = 0; i < MAX_THREADS; i++)
+ SitIdleEvent[i] = CreateEvent(0, FALSE, FALSE, 0);
+#endif
// Initialize SplitPointStack locks
for (i = 0; i < MAX_THREADS; i++)
lock_init(&(SplitPointStack[i][j].lock), NULL);
}
-#if !defined(_MSC_VER)
- pthread_mutex_init(&WaitLock, NULL);
- pthread_cond_init(&WaitCond, NULL);
-#else
- for (i = 0; i < MAX_THREADS; i++)
- SitIdleEvent[i] = CreateEvent(0, FALSE, FALSE, 0);
-#endif
-
// Will be set just before program exits to properly end the threads
AllThreadsShouldExit = false;
#if !defined(_MSC_VER)
ok = (pthread_create(pthread, NULL, init_thread, (void*)(&i)) == 0);
#else
- DWORD iID[1];
- ok = (CreateThread(NULL, 0, init_thread, (LPVOID)(&i), 0, iID) != NULL);
+ ok = (CreateThread(NULL, 0, init_thread, (LPVOID)(&i), 0, NULL) != NULL);
#endif
if (!ok)
for (int i = 0; i < MAX_THREADS; i++)
for (int j = 0; j < ACTIVE_SPLIT_POINTS_MAX; j++)
lock_destroy(&(SplitPointStack[i][j].lock));
+
+ lock_destroy(&WaitLock);
+ lock_destroy(&MPLock);
}