I'm writing a chess engine , and this is an example of how I want to implement the UCI protocol:
//search.h
#pragma once
#include<atomic>
static std::atomic_bool stop=false;
namespace Search
{
int Alphabeta()
{
int r = 10;
int Rounds = 0;
while ((++Rounds<20)&&!stop)
{
int sum = 0;
for (size_t i = 0; i < 100000000; i++)
{
sum += i;
}
sync_cout << sum<< sync_endl;
}
sync_cout << "Stopping" << sync_endl;
return r;
}
}
//UCI.h
#pragma once
#include<iostream>
#include<string>
#include <sstream>
#include<thread>
#include<mutex>
#include<condition_variable>
enum SyncCout { IO_LOCK, IO_UNLOCK };
//taken from StockFish
std::ostream& operator<<(std::ostream& os, SyncCout sc) {
static std::mutex m;
if (sc == IO_LOCK) m.lock();
if (sc == IO_UNLOCK) m.unlock();
return os;
}
#define sync_cout std::cout << IO_LOCK
#define sync_endl std::endl << IO_UNLOCK
#include"search.h"
class Thread
{
public:
Thread()
{
nativeThread = std::thread(&Thread::MainLoop, this);
sync_cout << "#Constructor" << sync_endl;
}
void MainLoop()
{
while (!exit)
{
while (pause)
{
sync_cout << "#Waiting" << sync_endl;
std::unique_lock<std::mutex> lk(mutex);
cv.wait(lk);
lk.unlock();
}
sync_cout << "#UCILoop" << sync_endl;
std::string token, cmd;
while (!pause && !exit && std::getline(std::cin, cmd))
{
sync_cout << "#Processing" << sync_endl;
std::istringstream is(cmd);
is >> std::skipws >> token;
if (token == "stop")
{
stop = true;
PauseThread();
}
else if (token == "isready") std::cout << "readyok" << std::endl;
else if (token == "pause") PauseThread();
}
}
}
void PauseThread()
{
//pause
std::lock_guard<std::mutex> lk(mutex);
pause = true;
}
void ResumeThread()
{
std::lock_guard<std::mutex> lk(mutex);
pause = false;
cv.notify_one();
}
~Thread()
{
sync_cout << "#Destructor" << sync_endl;
mutex.lock();
pause = false;
exit = true;
cv.notify_one();
mutex.unlock();
nativeThread.join();
}
private:
std::thread nativeThread;
std::mutex mutex;
std::condition_variable cv;
bool pause = true, exit = false;
};
namespace UCI
{
void Loop()
{
Thread th;
std::cout << "#PrimaryLoop : "<<std::endl;
std::string token, cmd;
while (std::getline(std::cin, cmd))
{
std::cout << "Processing : ";
std::istringstream is(cmd);
is >> std::skipws >> token;
if (token == "go")
{
std::cout << "go ok" << std::endl;
stop = false;
th.ResumeThread();
Search::Alphabeta();
th.PauseThread();
}
else if (token == "isready") std::cout << "readyok" << std::endl;
else if (token == "quiet")
{
std::cout << "quieting" << std::endl;
break;
}
}
}
}
and main :
#include"UCI.h"
int main()
{
UCI::Loop();
}
Everything works ok with the only exception being the case when the search finishes normally without receiving the UCI command "stop" , so the search will return while the secondary UCI thread is waiting for input #"std::getline" , I intended to write to the stdin stream "pause" as can be seen from the code before knowing that this is at the very best non portable & wrong , what are my options or is there another way to pause a thread regardless of what it's currently executing ?
Related
This should be a normal timer that runs until it's either paused or exited. The code is exited by the NextStep() Function. And The timer is supposed to pause and stay paused until it's pressed again.
However, when I press the spacebar, the timer stops only after adding another digit to the timer.
An example of the problem:
01sec
02sec
I press the spacebar.
03sec (+1sec)
The timer pauses.
On the other hand, the code that executes the NextStep() works fine without any delays.
I tried rewriting it in different ways, but none of them worked.
#pragma once
#include <chrono>
#include <iostream>
#include <string>
#include <thread>
#include <stdlib.h>
#include <iomanip>
#include <math.h>
#include <windows.h>
#include <conio.h>
#include <thread>
using namespace std;
void NextStep();
bool pause = false;
bool stop = false;
void wait(int milliseconds)
{
int counter = 0;
while (pause) {
char ch = _getch();
if (ch == ' ')
{
pause = !pause;
}
else if (ch == 27)
{
cout << "\033c";
NextStep();
stop = true;
}
}
while (counter < milliseconds && !stop)
{
if (pause) {
continue;
}
if (pause == false) {
this_thread::sleep_for(chrono::milliseconds(1));
counter++;
}
}
}
void timer()
{
int seconds = 0;
int minutes = 0;
int hours = 0;
while (true)
{
cout << "\033c";
cout << setfill(' ') << setw(55) << " Timer \n";
cout << " ";
cout << setfill('0') << setw(2) << hours << "h ";
cout << setfill('0') << setw(2) << minutes << "min ";
cout << setfill('0') << setw(2) << seconds << "sec ";
wait(60);
seconds++;
if (seconds == 60) {
minutes++;
seconds = 0;
}
else if (minutes == 60)
{
hours++;
minutes = 0;
seconds = 0;
}
if (_kbhit())
{
char ch = _getch();
if (ch == ' ')
{
pause = !pause;
}
else if (ch == 27)
{
cout << "\033c";
NextStep();
stop = true;
break;
}
}
}
}
Here's the NextStep() function:
void NextStep()
{
string option;
correct = false;
cout << "\033c";
cout << "Loading...";
Sleep(1300);
cout << "\033c";
cout << "What would you like to do next?" << endl;
cout << "" << endl;
cout << "To change your password TYPE: password" << endl;
cout << "To use a calculator TYPE: calculator" << endl;
cout << "To use a timer TYPE: timer" << endl;
cout << "" << endl;
cout << "Type your choice: ";
UserInput();
}
I'm not sure I understand all the workings of your code, but I think I understand that you need to have a timer that can be started, paused, and restarted. Also if I understood correctly the timer should not be affected (= paused) by the fact that the thread is in sleep.
So, here is an implementation of such a timer that might help you (at least for part of your problem) :
#include <chrono>
template<typename T>
class Timer
{
public:
void start()
{
m_start = std::chrono::steady_clock::now();
}
void pause()
{
m_elapsed += get_current_elapsed();
m_start = {};
}
void reset()
{
m_start = {};
m_elapsed = {};
}
int64_t get_elapsed()
{
return (m_elapsed + get_current_elapsed()).count();
}
private:
std::chrono::time_point<std::chrono::steady_clock> m_start{};
T m_elapsed{};
bool is_started()
{
return m_start.time_since_epoch() != T{};
}
T get_current_elapsed()
{
return is_started() ? std::chrono::duration_cast<T>(std::chrono::steady_clock::now() - m_start) : T{};
}
};
And here is an example of how it can be used :
#include <iostream>
#include <thread>
int main()
{
Timer<std::chrono::seconds> timer;
timer.start();
std::this_thread::sleep_for(std::chrono::seconds(1));
timer.pause(); // "optional"
std::cout << timer.get_elapsed() << std::endl; // 1
timer.start(); // "optional"
std::this_thread::sleep_for(std::chrono::seconds(1));
timer.pause(); // "optional"
std::cout << timer.get_elapsed() << std::endl; // 2
timer.reset();
timer.start();
std::this_thread::sleep_for(std::chrono::seconds(1));
timer.pause(); // "optional"
std::cout << timer.get_elapsed() << std::endl; // 1
return 0;
}
Timer is a template, so instead of std::chrono::seconds you can use any of the following types depending on the precision you want for the timer :
std::chrono::nanoseconds
std::chrono::microseconds
std::chrono::milliseconds
std::chrono::seconds
std::chrono::minutes
std::chrono::hours
std::chrono::days
std::chrono::years
I am trying to write a simple, thread-safe blocking queue for my application. For whatever reason in my demo app, not all threads are waking up when the call to close() is made. My consumer thread closes just fine but the other 2 producer threads never receive the signal. Perhaps a race condition?
This is my demo application:
#include <iostream>
#include <string>
#include <sstream>
#include <mutex>
#include "blocking_queue.h"
rl::blocking_queue<std::string> queue(3);
std::string random_string(size_t);
int main()
{
std::thread consumer([]() {
std::string message;
while (queue.pop(message)) {
std::cout << "--> async_write(...) called with:" << message << std::endl;
std::thread popper([]() {
std::this_thread::sleep_for(std::chrono::milliseconds(200));
std::cout << "--> async_write(...) completed, queue size is now " << queue.size() << std::endl;
queue.unblock();
});
popper.detach();
if (!queue.block()) {
break;
}
}
std::cout << "consumer thread closed" << std::endl;
});
std::thread producer([]() {
while (!queue.closed()) {
std::string id = random_string(6);
std::this_thread::sleep_for(std::chrono::milliseconds(50));
std::cout << id << ": Pushing JSON" << std::endl;
queue.push("a message");
std::cout << id << ": Pushed JSON" << std::endl;
}
std::cout << "producer closed" << std::endl;
});
std::thread producer2([]() {
while (!queue.closed()) {
std::string id = random_string(6);
std::this_thread::sleep_for(std::chrono::milliseconds(50));
std::cout << id << ": Pushing heartbeat" << std::endl;
queue.push("a heartbeat");
std::cout << id << ": Pushed heartbeat" << std::endl;
}
std::cout << "producer2 closed" << std::endl;
});
std::thread cancel([]() {
std::this_thread::sleep_for(std::chrono::milliseconds(10000));
std::cout << "%%%% CLOSING QUEUE %%%%" << std::endl;
queue.close();
std::cout << "%%%% QUEUE CLOSED %%%%" << std::endl;
});
cancel.join();
std::this_thread::sleep_for(std::chrono::milliseconds(10000));
std::cout << "Hello World!\n";
return EXIT_SUCCESS;
}
std::string random_string(size_t length)
{
auto randchar = []() -> char
{
const char charset[] =
"0123456789"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ";
const size_t max_index = (sizeof(charset) - 1);
return charset[rand() % max_index];
};
std::string str(length, 0);
std::generate_n(str.begin(), length, randchar);
return str;
}
This is my blocking queue:
#include <queue>
#include <mutex>
#include <condition_variable>
#include <assert.h>
// Based on https://www.justsoftwaresolutions.co.uk/threading/implementing-a-thread-safe-queue-using-condition-variables.html
namespace rl {
template<typename T>
class blocking_queue {
private:
std::queue<T> queue;
const size_t queue_limit;
bool is_closed = false;
mutable std::mutex queue_mutex;
std::condition_variable new_item_or_closed_event;
std::condition_variable item_removed_event;
std::condition_variable queue_blocked_event;
#ifndef NDEBUG
size_t pushes_in_progress = 0;
#endif
public:
blocking_queue(size_t size_limit = 0) : queue_limit(size_limit) {}
void push(const T& data) {
std::unique_lock<std::mutex> lock(queue_mutex);
#ifndef NDEBUG
++pushes_in_progress;
#endif
if (queue_limit > 0) {
while (queue.size() >= queue_limit) {
item_removed_event.wait(lock);
}
}
assert(!is_closed);
queue.push(data);
#ifndef NDEBUG
--pushes_in_progress;
#endif
lock.unlock();
new_item_or_closed_event.notify_one();
}
bool try_push(const T& data) {
std::unique_lock<std::mutex> lock(queue_mutex);
if (queue_limit > 0) {
if (queue.size() >= queue_limit) {
return false;
}
}
assert(!is_closed);
queue.push(data);
lock.unlock();
new_item_or_closed_event.notify_one();
return true;
}
void close() {
std::unique_lock<std::mutex> lock(queue_mutex);
assert(!is_closed);
#ifndef NDEBUG
assert(pushes_in_progress == 0);
#endif
is_closed = true;
lock.unlock();
//item_removed_event.notify_all();
//queue_blocked_event.notify_all();
new_item_or_closed_event.notify_all();
}
void open() {
is_closed = false;
}
bool block() {
std::unique_lock<std::mutex> lock(queue_mutex);
queue_blocked_event.wait(lock);
return !is_closed;
}
void unblock() {
queue_blocked_event.notify_one();
}
bool pop(T & popped_value) {
std::unique_lock<std::mutex> lock(queue_mutex);
while (queue.empty()) {
if (is_closed) {
return false;
}
new_item_or_closed_event.wait(lock);
}
popped_value = queue.front();
queue.pop();
item_removed_event.notify_one();
return true;
}
bool try_pop(T & popped_value) {
std::unique_lock<std::mutex> lock(queue_mutex);
if (queue.empty()) {
return false;
}
popped_value = queue.front();
queue.pop();
item_removed_event.notify_one();
return true;
}
bool empty() const {
std::unique_lock<std::mutex> lock(queue_mutex);
return queue.empty();
}
bool closed() const {
std::unique_lock<std::mutex> lock(queue_mutex);
return is_closed;
}
size_t limit() const {
return queue_limit;
}
size_t size() const {
std::unique_lock<std::mutex> lock(queue_mutex);
return queue.size();
}
};
}
I have a loop that waits for the event.
I want to be able to add a notifyAndWait() function
Im not to sure how i can add that to my current class
class Event
{
public:
Event() : _signalled(false) {}
void notify()
{
std::unique_lock<std::mutex> lock(_mutex);
_signalled = true;
_condvar.notify_one();
}
void wait()
{
std::unique_lock<std::mutex> lock(_mutex);
_condvar.wait(lock, [&] { return _signalled; }); // also takes care about spurious wakeup
_signalled = false; // auto-reset semantics
}
private:
std::mutex _mutex;
std::condition_variable _condvar;
bool _signalled;
};
You could use the same condition variable to pass a signal back to the calling thread, using a different flag. Something like this:
class Event
{
public:
Event() : _signalled(false) {}
void notify()
{
std::cout << "notifying" << '\n' << std::flush;
{
std::unique_lock<std::mutex> lock(_mutex);
_completed = false;
_signalled = true;
}
_condvar.notify_one();
{
// now wait for completion
std::unique_lock<std::mutex> lock(_mutex);
_condvar.wait(lock, [&] { return _completed; });
}
std::cout << "completed" << '\n' << std::flush;
}
void wait()
{
{
std::unique_lock<std::mutex> lock(_mutex);
_condvar.wait(lock, [&] { return _signalled; });
_signalled = false;
}
// do stuff
auto n = hol::random_number(10);
std::cout << "doing " << n << " different things" << std::flush;
for(int i = 0; i < n; ++i)
{
std::cout << '.' << std::flush;
std::this_thread::sleep_for(std::chrono::milliseconds(hol::random_number(3000)));
}
std::cout << " done stuff" << '\n' << std::flush;
{
std::unique_lock<std::mutex> lock(_mutex);
_completed = true;
}
_condvar.notify_one();
}
private:
std::mutex _mutex;
std::condition_variable _condvar;
bool _signalled;
bool _completed;
};
int main()
{
Event e;
std::thread wait([&]{ e.wait(); });
e.notify();
wait.join();
}
I'm playing with C++(11) STL and got the following problem.
The basic idea for this code is:
I have a "trigger" function, an "add" function and a flag(false by default). If the flag is false the "add" function's going to push the threadID to a queue, otherwise it's going to insert the threadID to the set. When the trigger function is called, it set the flag to "true" and move threadIDs from the queue to the set.
I initialized 100 threads and use one of the thread to run the trigger function(in the code it's thread NO.30). Ideally the result should have 0 elements in the queue and 99 elements in the set.
However, sometimes the result is correct, sometimes I missed some numbers in the set, and sometimes I got the EXC_BAD_ACCESS error.
Could anyone help? Thank you.
#include <iostream>
#include <thread>
#include <vector>
#include <unordered_set>
#include <queue>
#include <mutex>
#include <atomic>
using namespace std;
bool flag = false;
queue<int> q;
unordered_set<int> s;
mutex mu;
void trigger()
{
mu.lock();
flag = true;
mu.unlock();
while( !q.empty() ){
s.insert(q.front());
q.pop();
}
}
void add(int id)
{
mu.lock();
if( !flag )
q.push(id);
else {
if ( s.find(id) == s.end() ){
s.insert(id);
}
}
mu.unlock();
}
void missing()
{
cout << "Missing Numbers: ";
for (int i = 1; i <= 100; i++) {
if( s.find(i) == s.end() )
cout << i << " ";
}
cout << endl;
}
int main()
{
vector<thread> threads;
for (int i = 0; i < 100; i++){
if ( i == 29 ) threads.push_back(thread(trigger));
else threads.push_back(thread(add, i+1));
}
for (int i = 0; i < 100; i++){
threads[i].join();
}
cout << "Q size: " << q.size() << endl;
cout << "S size: " << s.size() << endl;
missing();
}
You have 1 thread executing the trigger function and many threads executing the add function. Furthermore, you take care to guard some of the shared state but not all of it. See my comments/questions in the below code snippets.
void trigger()
{
// Only the 'flag' is protected from concurrent acceess
mu.lock();
flag = true;
mu.unlock();
// Why isn't 'q' or 's' protected by a lock?
while( !q.empty() ){
s.insert(q.front());
q.pop();
}
}
void add(int id)
{
// In this function both 'q' and 's' are protected from concurrent access
mu.lock();
if( !flag )
q.push(id);
else {
if ( s.find(id) == s.end() ){
s.insert(id);
}
}
mu.unlock();
}
Possible Solution
In general, you should protect any state being accessed concurrently. I'd also recommend using a lock type (e.g., lock_guard) instead of locking and unlocking the mutex directly (research RAII for why this is encouraged).
#include <iostream>
#include <mutex>
#include <queue>
#include <thread>
#include <unordered_set>
#include <vector>
using namespace std;
bool flag = false;
queue<int> q;
unordered_set<int> s;
mutex mu;
void trigger()
{
lock_guard<mutex> lock(mu);
flag = true;
while (!q.empty())
{
s.insert(q.front());
q.pop();
}
}
void add(int id)
{
lock_guard<mutex> lock(mu);
if (!flag)
{
q.push(id);
}
else
{
if (s.find(id) == s.end())
{
s.insert(id);
}
}
}
void missing()
{
cout << "Missing Numbers: ";
for (int i = 1; i <= 100; ++i)
{
if (s.find(i) == s.end())
{
cout << i << " ";
}
}
cout << endl;
}
int main()
{
vector<thread> threads;
for (int i = 0; i < 100; ++i)
{
if (i == 29)
{
threads.push_back(thread(trigger));
}
else
{
threads.push_back(thread(add, i + 1));
}
}
for (int i = 0; i < 100; ++i)
{
threads[i].join();
}
cout << "Q size: " << q.size() << endl;
cout << "S size: " << s.size() << endl;
missing();
return 0;
}
I can't figure out where is the problem with this simple code, I think that here is the trouble with output to Console maybe deadlock or something, can somebody, please help.
#include <iostream>
#include <string>
#include <sstream>
#include <boost/thread.hpp>
using namespace std;
struct IntegrateTask
{
int id;
double from, to, step, result;
IntegrateTask(int id, double from, double to, double step)
{
this -> id;
this -> from = from;
this -> to = to;
this -> step = step;
}
~IntegrateTask()
{}
};
vector<IntegrateTask> * tasks = new vector<IntegrateTask>();
boost::mutex mutlist;
boost::mutex iomutex;
boost::condition_variable condtask;
bool isInterrupted = false;
double foo(double x)
{
return x * x;
}
void integrate(IntegrateTask * task)
{
double result = 0;
double step = task -> step;
for(double i = task -> from ; i != task -> to; i =+ step)
{
result += foo(i) * step;
}
task -> result = result;
}
void integrateThread()
{
boost::thread::id id = boost::this_thread::get_id();
try
{
{
boost::mutex::scoped_lock iolock(iomutex);
cout << "Thread #" << id << " is working!" << endl;
}
while(!isInterrupted)
{
IntegrateTask * currtask = NULL;
{
boost::mutex::scoped_lock lock(mutlist);
while(!isInterrupted && tasks -> empty())
{
condtask.wait(lock);
}
if (!tasks -> empty())
{
currtask = &tasks->back();
tasks->pop_back();
}
}
if (currtask != NULL)
{
integrate(currtask);
boost::mutex::scoped_lock iolock(iomutex);
cout << "Task #" << (currtask->id) << "; result = " << (currtask->result) << endl;
}
}
boost::mutex::scoped_lock iolock(iomutex);
cout << "Thread # " << id << " stoped working normal!" << endl;
}
catch(boost::thread_interrupted)
{
boost::mutex::scoped_lock ioLock(iomutex);
cout << "Thread # " << id << " stoped working by interruption!" << endl;
}
catch(exception & e)
{
boost::mutex::scoped_lock iolock(iomutex);
cout << "Error: " << e.what() << endl;
}
}
int main()
{
cout << "Function for integration: f(x)=x*x" << endl;
cout << "For stopping program press EXIT" << endl;
int thcount = 6;// or boost::thread::hardware_concurrency()
boost::thread_group thgroup;
for (int i = 1; i <= thcount; i++){
thgroup.create_thread(&integrateThread);
}
int id = 0;
while (true)
{
string line;
{
boost::mutex::scoped_lock iolock(iomutex);
cout << "Task #" << ++id << "; left bound, right bound and step: ";
getline(cin, line);
}
if (line.find("e") != string::npos)
{
isInterrupted = true;
condtask.notify_all();
thgroup.interrupt_all();
thgroup.join_all();
return 0;
}
double from, to, step;
istringstream input(line);
input >> from >> to >> step;
IntegrateTask * task = new IntegrateTask(id, from, to, step);
{
boost::mutex::scoped_lock lock(mutlist);
tasks->push_back(*task);
}
condtask.notify_one();
}
}
I haven't tried to follow the logic of what you're aiming to achieve here, but there are 2 issues (at least):
You're not using id in IntegrateTask's constructor. You should generally favour initialisation lists over assignments in constructor bodies, and using class member variable names in function signatures is a recipe for disaster too, so I'd change your constructor to:
IntegrateTask(int id_init, double from_init, double to_init, double step_init)
: from(from_init), to(to_init), step(step_init), id(id_init) {}
The probable cause of the hanging is your use of != in the for loop in integrate. If you change that to < your program shouldn't hang, but I'm not sure if this breaks your program's logic.