I have a problem with waking a thread in C++. I have 4 running threads. I want to wake my sleeping thread when the 4 running threads are completed. I did it with condition wait operation but it doesn't look good. How can I do this process in a better quality way?
4 tasks are triggered by broadcast and starts working on different cores at the same time. At the end of each task, it sets the flag of its own taskID to 1 and sends a signal to the sleeping task. The task in sleep state wakes up every time it receives a signal and checks the flag of each task. If the 4 task flag is 1, it continues and does its own work.
void *thread_sleep( void *arg )
{
pthread_mutex_lock(&mutex_sleep);
while(flag_task[0] == 0 || flag_task[1] == 0 || flag_task[2] == 0 || flag_task[3] == 0)
pthread_cond_wait(&cond_sleep, &mutex_sleep);
/*
.
.
.
.
*/
flag_task[0] = 0;
flag_task[1] = 0;
flag_task[2] = 0;
flag_task[3] = 0;
pthread_mutex_unlock(&mutex_sleep);
}
void *thread( void *arg)
{
int taskID = *(char *)arg - '0';
while(1)
{
pthread_mutex_lock(&mutex[taskID]);
pthread_cond_wait(&cond, &mutex[taskID]);
/*
.
.
.
.
*/
pthread_mutex_unlock(&mutex[taskID]);
flag_task[taskID] = 1;
pthread_cond_signal(&cond_sleep);
}
}
int main()
{
pthread_create( &pthread1, NULL, thread, (void *)"0" );
pthread_create( &pthread2, NULL, thread, (void *)"1" );
pthread_create( &pthread3, NULL, thread, (void *)"2" );
pthread_create( &pthread4, NULL, thread, (void *)"3" );
pthread_create( &pthread5, NULL, thread_sleep, (void *)"4" );
pthread_cond_broadcast(&cond);
}
I solved using barrier. Thank you #Quimby.
void *thread_sleep( void *arg )
{
pthread_mutex_lock(&mutex_sleep);
pthread_cond_wait(&cond_sleep, &mutex_sleep);
/*
.
.
.
.
*/
pthread_mutex_unlock(&mutex_sleep);
}
void *thread( void *arg)
{
int taskID = *(char *)arg - '0';
while(1)
{
pthread_mutex_lock(&mutex[taskID]);
pthread_cond_wait(&cond, &mutex[taskID]);
/*
.
.
.
.
*/
pthread_mutex_unlock(&mutex[taskID]);
pthread_barrier_wait(&barrier);
pthread_cond_signal(&cond_sleep);
}
}
int main()
{
pthread_barrier_init(&barrier, NULL, 4);
pthread_create( &pthread1, NULL, thread, (void *)"0" );
pthread_create( &pthread2, NULL, thread, (void *)"1" );
pthread_create( &pthread3, NULL, thread, (void *)"2" );
pthread_create( &pthread4, NULL, thread, (void *)"3" );
pthread_create( &pthread5, NULL, thread_sleep, (void *)"4" );
sleep(1);
pthread_cond_broadcast(&cond);
}
Related
I am running this g_test where I simply initialize and close a client.
TEST(safIpc, createAndCloseClient)
{
std::shared_ptr<fnv::ipcsvc::IpcSvc> safIpc = std::make_shared<fnv::ipcsvc::IpcSvc>();
const std::string& app1 {"/testApp1"};
const std::string& groupName {"wir_clients"};
fnv::ipcsvc::IpcSvcAttrMq attr(fnv::ipcsvc::IpcSvcAttrType::MQ_CLIENT,
app1,
groupName,
"/server");
std::shared_ptr<IpcSvcTestSafHandler> msgHandler = std::make_shared<IpcSvcTestSafHandler>();
// initialize the ipc library
IpcSvcPriv::SharedPtr ipcPrivData {nullptr};
fnv::ipcsvc::IpcSvcRet ret = safIpc->init(attr, msgHandler, ipcPrivData);
EXPECT_EQ(ret, fnv::ipcsvc::IpcSvcRet::SUCCESS);
EXPECT_NE(ipcPrivData, nullptr);
ret = safIpc->close(ipcPrivData, app1); //HANGS here
EXPECT_EQ(fnv::ipcsvc::IpcSvcRet::SUCCESS, ret);
}
In init I create 3 threads: (here is the relevant part of the init code):
1- A process thread
2- a Receive thread
3- A timer thread
int rc = pthread_create(&m_timerThread,
NULL,
&IpcSvcImpl::timer_start,
this);
if (rc != 0)
{
ipcSvcLog(LOGE, "Failed to create timer thread!");
close(tmpPrivData,
attr.getAppId());
return error;
}
pthread_setname_np(m_timerThread,
"IpcSvcTimerThread");
}
// Start the worker threads
int rc = pthread_create(&m_receiveThread,
NULL,
&IpcSvcImpl::receive,
this);
if (rc != 0)
{
//TODO some error log
close(tmpPrivData,
attr.getAppId());
return error;
}
pthread_setname_np(m_receiveThread,
"IpcSvcReceiveThread");
rc = pthread_create(&m_processThread,
NULL,
&IpcSvcImpl::process,
this);
if (rc != 0)
{
//TODO some error log
close(tmpPrivData,
attr.getAppId());
return error;
}
pthread_setname_np(m_processThread,
"IpcSvcProcessThread");
Here is the close function:
IpcSvcRet IpcSvcImpl::close(IpcSvcPriv::SharedPtr privateData,
const std::string& appId)
{
if (!privateData)
{
//TODO log about client not providing sane private data
return IpcSvcRet::FAIL;
}
// acquire the mutex and set close called to true
{
std::lock_guard<std::mutex> guard(m_closeMtx);
m_closed = true;
}
if (m_msgQueue)
{
m_msgQueue->mutexInit();
// writing dummy message to process thread
std::pair<std::array<uint8_t, IPCSVC_MAX_MSG_SIZE>, ssize_t> queueMsg;
m_msgQueue->enqueue(queueMsg);
}
// writing dummy message to receive thread
uint32_t buffer = 0;
sendData(privateData,
(void*)&buffer,
sizeof(uint32_t),
appId);
pthread_join(m_receiveThread,
NULL);
pthread_join(m_processThread,
NULL);
if (m_isClient)
{
m_cv.notify_one();
printf("timer thread hangs\n"); // HANGS HERE ///////////////////////////////////////
pthread_join(m_timerThread,
NULL);
//This line is never reached..
}
delete m_msgQueue;
m_msgQueue = nullptr;
// close the ipc layer
if (m_ipc)
{
m_ipc->close();
delete m_ipc;
m_ipc = nullptr;
}
m_clientsList.clear();
m_hbManager = { };
return IpcSvcRet::SUCCESS;
}
Here is the timer_start function:
The timer thread is a timer that is keeps looping forever unless the fc->m_closed is set to true. It triggers fc->timerExpiry() every 2 seconds.
// timer thread entry
void* IpcSvcImpl::timer_start(void *arg)
{
if (!arg)
{
return nullptr;
}
printf("starting timer\n");
IpcSvcImpl* fc = static_cast<IpcSvcImpl *>(arg);
std::unique_lock<std::mutex> lock(fc->m_closeMtx);
while (!(fc->m_closed))
{
printf("Entering loop\n");
lock.unlock();
auto expireAt = std::chrono::steady_clock::now() +
std::chrono::seconds(fc->getTimerInterval());
fc->timerExpiry();
lock.lock();
printf("here?\n");
fc->m_cv.wait_until(lock, expireAt);
printf("Here 2\n");
}
printf("Exited loop\n\n");
return nullptr;
}
The output of the unittest:
[----------] 5 tests from safIpc
[ RUN ] safIpc.createAndCloseClient
starting timer
Entering loop
closing..
timer thread hangs
pthread join hangs forever, I am not sure why. The "here" prints are never hit, which seems odd.
Thanks for the help!
I have three threads - Thread1 prints "Good", Thread2 prints "Morning" and Thread3 prints "All". How do I use these threads to keep printing “Good Morning All” on the screen continuously?
For one, you are simply wasting resources.
However, assuming that you really need this to accomplish something more important than just printing words, here is a suggestion:
create 3 mutexes (pthread_mutex)
pthread_mutex_t m_Good, m_Morning, m_all;
pthread_mutex_init(&m_Good, NULL);
pthread_mutex_init(&m_Morning, NULL);
pthread_mutex_init(&m_All, NULL);
Lock last two mutexes
pthread_mutex_lock(&m_Morning);
pthread_mutex_lock(&m_All);
In first thread prints its message then unlock second mutex.
while(true){
if(pthread_mutex_lock(&m_Good)==0){
printf("GOOD ");
pthread_mutex_unlock(&m_Morning);
pthread_mutex_lock(&m_Good);
}
}
second thread prints message, locks its mutex and unlock third
third thread prints its message, unlock first mutex and locks third mutex
Here's a simple lock-free implementation for forcing sequential execution of threads. It uses an atomic state variable that can represent four possible states:
working = one of the threads is working
ready_for_task1 = it is task1's turn to start working
ready_for_task2 = it is task2's turn to start working
ready_for_task3 = it is task3's turn to start working
The general idea is to cycle through these states:
ready_for_task1 ->
working ->
ready_for_task2 ->
working ->
ready_for_task3 ->
working ->
ready_for_task1 ->
...
First part, define the states, declare the global atomic state, and define a guard class that performs the state transitions. The guard constructor of the guard will "busy" wait by atomically checking for its ready state and switching the state to working. The guard destructor will set the state to the next task's ready state.
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <atomic>
enum State { ready_for_task1, ready_for_task2, ready_for_task3, working };
static std::atomic< State > state_;
class TransitionGuard {
public:
TransitionGuard(State start, State finish) : finish_(finish) {
State expecting = start;
while( !state_.compare_exchange_weak( expecting, working ) ) {
expecting = start;
asm("pause");
}
}
~TransitionGuard() {
state_.store( finish_ );
}
private:
const State finish_;
};
Then each thread runs their own loop, printing their word under their respective transition guard.
void * task1( void * data )
{
while( true ) {
TransitionGuard guard( ready_for_task1, ready_for_task2 );
printf( "Good" );
}
}
void * task2( void * data)
{
while( true ) {
TransitionGuard guard( ready_for_task2, ready_for_task3 );
printf( " Morning" );
}
return NULL;
}
void * task3( void * data)
{
while( true ) {
TransitionGuard guard( ready_for_task3, ready_for_task1 );
printf( " All\n" );
}
return NULL;
}
And finally, you'll want to initialize the state before creating the threads.
int main( int argc, const char ** argv )
{
state_ = ready_for_task1;
pthread_t thread1, thread2, thread3;
if( pthread_create( &thread1, NULL, task1, NULL ) )
{
fprintf( stderr, "thread1 failed to start\n" );
exit(EXIT_FAILURE);
}
if( pthread_create( &thread2, NULL, task2, NULL ) )
{
fprintf( stderr, "thread2 failed to start\n" );
exit(EXIT_FAILURE);
}
if( pthread_create( &thread3, NULL, task3, NULL ) )
{
fprintf( stderr, "thread3 failed to start\n" );
exit(EXIT_FAILURE);
}
pthread_join( thread1, NULL );
pthread_join( thread2, NULL );
pthread_join( thread3, NULL );
fprintf( stderr, "threads joined. exiting.\n" );
exit(EXIT_SUCCESS);
}
i build Simple Anticheat module for a game and i need protect the Thread's from a Suspend (Like Suspend Thread from Processhacker).
Is there any way to automatically resume the thread if is suspended?
Here is my module code:
#include "stdafx.h"
#include "Start.h"
void Msg_Sf_Br(){
MessageBoxA(NULL,"SpeedHack - Detect", load.Nome_das_Janelas, MB_SERVICE_NOTIFICATION | MB_ICONWARNING);
ExitProcess(0);
}
void Msg_Sf_En(){
MessageBoxA(NULL,"SpeedHack - Detect", load.Nome_das_Janelas, MB_SERVICE_NOTIFICATION | MB_ICONWARNING);
ExitProcess(0);
}
void Speed_perf()
{
if( *(unsigned long*)QueryPerformanceCounter != 2337669003 ){
if (load.Log_Txt_Hack == 1){
}
if (load.Message_Warning_En == 1){
ExitProcess(0);
}
if (load.Message_Warning_En == 2){
CreateThread(NULL,NULL,LPTHREAD_START_ROUTINE(Msg_Sf_Br),NULL,0,0);
Sleep(3000);
ExitProcess(0);
}
if (load.Message_Warning_En == 0){
ExitProcess(0);
}
else
ExitProcess(0);
}
}
void performance(){
if (load.Anti_Kill_Scans == 1)
{
again:
Speed_perf();
Sleep(load.Detecta_Speed_PerformanceT);
goto again;
}
else
{
again2:
Speed_perf();
Sleep(load.Detecta_Speed_PerformanceT);
goto again2;
}
}
void SPerformance(){
CreateThread(NULL,NULL,LPTHREAD_START_ROUTINE(performance),NULL,0,0);
}
Any idea?
With a little trick you can hide your thread from any debugger or tools like process hacker.
void func()
{
}
int main()
{
int(__stdcall* ZwCreateThreadEx)(HANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES, HANDLE, PVOID, PVOID, ULONG, ULONG_PTR, SIZE_T, SIZE_T, PVOID) = (decltype(ZwCreateThreadEx))GetProcAddress(GetModuleHandle("ntdll.dll"),"ZwCreateThreadEx");
HANDLE hThread=0;
ZwCreateThreadEx(&hThread,0x1FFFFF,0,GetCurrentProcess(),
(LPTHREAD_START_ROUTINE)func,0, 0x4/*hide flag*/,0,0x1000,0x10000,0);
return 0;
}
You can do it this way:
get list of process thread ids, using CreateToolhelp32Snapshot
go to first thread using methods: Thread32First.
for each found thread (you should check if belong to the given process):
then Open the thread using OpenThread in manner to retrieve handle to the thread from it thread id,
when you have the handle, you can suspend the thread using SuspendThread in manner to retrieve the previous suspension count,
then you can Resume the thread until it suspension count is 0. you must resume at least once in manner to cancel the suspension from the previous step.
if thread are not allowed to be suspended, you can use ResumeThread just to get the suspension count even if it was not suspended.
Close the thread handle using CloseHandle
iterate to next thread use Thread32Next.
In manner to be able to do the whole thing you must run as administrator.
Here is an example:
void TraverseProcessThreads(DWORD pid)
{
HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0); //get list of all system thread
if( hSnapshot == INVALID_HANDLE_VALUE)
{
//print error and return;
return;
}
THREADENTRY32 threadEntry;
if( Thread32First( hSnapshot, &threadEntry) )
{
size_t threadsCounter = 0, suspendedThreadsCounter=0;
do{
if(te.th32OwnerProcessID == pid) //we get all threads in system, should filter the relevant pid.
{
threadsCounter ++; //found thread
HANDLE hThread = OpenThread(THREAD_ALL_ACCESS,FALSE,te.th32ThreadID); //get handle to thread from its thread id
if(hThread == NULL) //
{
//print error and break. (will be permission error if not administrator)
break;
}
int suspensionCount = SuspendThread( hThread ) ;//will return previous suspension count. you can also use ResumeThread if there's no way it can be suspended.
if(suspensionCount > 0)
{
//thread was suspended
suspendedThreadsCounter ++;
}
//cancel our suspension...
suspensionCount = ResumeThread(hThread );
/*to resume suspended thread use ResumeThread until it return 1.
do{
suspensionCount = ResumeThread(hThread );
}while (suspensionCount > 1); //similar to Suspend Resume return previous Suspention count.
*/
}
CloseHandle(hThread);
}while(Thread32Next( hSnapshot, &threadEntry) );
//print results:
cout<<"process id"<<pid<<endl<<" has "<<threadsCounter <<" threads " <<endl
<<suspendedThreadsCounter <<" threads was suspended"<<endl;
}
else{
//print some error...
}
CloseHandle(hSnapshot);
}
UPDATE: I found that the semaphore they are releasing is not the semaphore the monitor thread is waiting! I used cout<<ready to find the semaphore the threads are releasing is 00000394, which is not the handle of the semaphore the monitor thread is waiting for. What is the possible reason for this problem? Thank you!
I am new to multithread programming in Windows. Today when I'm writing my online game server, I try to use semaphores in Windows. It is written based on IOCP so that every message is handled in a separate thread. A game consists 4 players.
What I expect it to do is: when receiving a message, a new thread starts and release a ready. There is a monitor thread waiting for 4 ready, and then releases 4 all_ready. Each thread waits one all_ready and goes on.
The code is here:
CGameHost is a manager for a 4-player game.
CGameHost::CGameHost(void)
{
init_times=0;
ready = CreateSemaphore(NULL, 0, 4, NULL);
read = CreateSemaphore(NULL, 0, 4, NULL);
all_ready = CreateSemaphore(NULL, 0, 4, NULL);
all_read = CreateSemaphore(NULL, 0, 4, NULL);
monitor_thread = (HANDLE)_beginthreadex(NULL, 0, Monitor, (LPVOID)this, NULL, 0);
}
unsigned __stdcall CGameHost::Monitor( LPVOID p ) // a static function
{
CGameHost *nowp = (CGameHost *)p;
while(true)
{
int i;
for(i=1;i<=MAX_PLAYER;i++)
{
WaitForSingleObject(nowp->ready, INFINITE);//stuck here
cout<<"Get Ready!"<<endl; // This is not outputed, which means it stucks in the last row.
}
for(i=1;i<=MAX_PLAYER;i++)
{
ReleaseSemaphore(nowp->all_ready, 1, NULL);
}
for(i=1; i<=MAX_PLAYER; i++)
{
WaitForSingleObject(nowp->read, INFINITE);
}
for(i=1; i<=MAX_PLAYER;i++)
{
ReleaseSemaphore(nowp->all_read, 1, NULL);
}
}
return 0;
}
void CGameHost::ReleaseReady()
{
ReleaseSemaphore(ready, 1, NULL);
}
void CGameHost::WaitAllReady()
{
WaitForSingleObject(all_ready, INFINITE);
}
void CGameHost::ReleaseRead()
{
ReleaseSemaphore(read, 1, NULL);
}
void CGameHost::WaitAllRead()
{
WaitForSingleObject(all_read, INFINITE);
}
DataProcess::Game is the message handler for incoming game messages.
CMessage Dataprocess::Game( CMessage* recv_msg )
{
CMessage ret;
int now_roomnum = recv_msg->para1;
int now_playernum = recv_msg->para2;
if(true)
{
cout<<"Received Game Message: "<<endl;
cout<<"type2 = "<<recv_msg->type2;
cout<<" player_num = "<<now_playernum<<" msg= "<<recv_msg->msg<<endl;
}
if(recv_msg->type2 == MSG_GAME_OPERATION)
{
ret.type1 = MSG_GAME;
ret.type2 = MSG_GAME_OPERATION;
cout<<"Entered from "<<now_playernum<<endl;
game_host[now_roomnum].SetMessage(now_playernum, recv_msg->msg);
game_host[now_roomnum].ReleaseReady();
cout<<"Released Ready from "<<now_playernum<<endl;//this is shown
game_host[now_roomnum].WaitAllReady();//stuck here
cout<<"AllReady from"<<now_playernum<<endl;//not shown
}
return ret;
}
Your reply will be of great help for a beginner of Windows multithread programmer like me! Thank you!
If I understood your needs, you should probably have something like this..
HANDLE hPlayersReady[4];
HANDLE hAllPlayed;
Create these 5 events, and then on your monitor thread,
do something like this...
while(true)
{
// Wait for all players to move
WaitForMultipleObjects(4, &hPlayersReady, true, INFINITE);
// Process move
...
// Advise players the move was processed...
SetEvent(hAllPlayed);
}
And on your player thread X
while(true)
{
// Make my move
...
// Advise monitor I'm ready
SetEvent(hPlayersReady[X]);
// Wait for ready to do another move
WaitForSingleObject(hAllPlayed);
}
Well, I solved it myself. The reason is that I used CreateSemaphore again after creating the thread, making the player thread visiting different semaphores as the monitor thread... Sorry for my stupidness, and thank you for telling me so much!
I have written a multithreaded program, in which three threads are trying to save the text to the same file. I applied the critical section. And under windows 7 works perfectly but in CE 6.0 does not sync, ie, each thread is trying at the same time to save:
It works now!!! Thanks Everyone for help!
Critical section:
InitializeCriticalSection(&CriticalSection);
// Create worker threads
for( i=0; i < THREADCOUNT; i++ )
{
aThread[i] = CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE) WriteToFile, NULL, 0, &ThreadID);
if( aThread[i] == NULL )
{
printf("CreateThread error: %d\n", GetLastError());
return 1;
}
}
// Wait for all threads to terminate
for( i=0; i < THREADCOUNT; i++ )
{
WaitResult = WaitForSingleObject(aThread[i], INFINITE);
switch(WaitResult)
{
case WAIT_OBJECT_0:
printf("Thread %d has terminated...\n", i);
break;
// Time out
case WAIT_TIMEOUT:
printf("The waiting is timed out...\n");
break;
// Return value is invalid.
default:
printf("Waiting failed, error %d...\n", GetLastError());
ExitProcess(0);
}
}
// Close thread handles
for( i=0; i < THREADCOUNT; i++ )
CloseHandle(aThread[i]);
// Release resources used by the critical section object.
DeleteCriticalSection(&CriticalSection);
Function called by a thread:
DWORD WINAPI WriteToFile( LPVOID lpParam )
{
// lpParam not used in this example
UNREFERENCED_PARAMETER(lpParam);
DWORD dwCount=1, dwWaitResult;
HANDLE hFile;
char DataBuffer[30];
DWORD dwBytesToWrite;
DWORD dwBytesWritten;
// Request ownership of the critical section.
EnterCriticalSection(&CriticalSection);
// Write to the file
printf("Thread %d writing to file...\n", GetCurrentThreadId());
hFile = CreateFile(TEXT("file.txt"), GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
SetFilePointer(hFile, 0, NULL, FILE_END);
while( dwCount <= 3 )
{
sprintf(DataBuffer, "Theard %d writing %d\n", GetCurrentThreadId(), dwCount);
dwBytesToWrite = (DWORD)strlen(DataBuffer);
WriteFile( hFile, DataBuffer, dwBytesToWrite, &dwBytesWritten, NULL);
printf("Theard %d wrote %d successfully.\n", GetCurrentThreadId(), dwCount);
}
}
dwCount++;
}
CloseHandle(hFile);
// Release ownership of the critical section.
LeaveCriticalSection(&CriticalSection);
return TRUE;
}
The problem is that you are passing TRUE to the fWaitAll flag for WaitForMultipleObjects. On Windows CE, this is not supported: the documentation on MSDN says that this flag must be FALSE. WaitForMultipleObjects is thus not waiting, but returning an error instead, but you are not checking the return code. The main thread thus goes straight through, closes the handles and deletes the critical section whilst the "worker" threads are still running. Once DeleteCriticalSection has been called, the critical section "can no longer be used for synchronization", so the EnterCriticalSection calls probably no longer block, and you end up with the scenario you have here.
On Windows 7, everything works because the WaitForMultipleObjects call does indeed wait for all the threads to finish.
Rather than using WaitForMultipleObjects, just use WaitForSingleObject in a loop to wait for each thread in turn.