thread sync problem

Hai :]
Beeing new to the subject I wrote the following:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
...

CONNECTION_ID          n2i;
CRITICAL_SECTION      cs;     
...
//in func that creates a new thread
EnterCriticalSection(&cs);//Wait for no other thread to be initing (not using n2i)
//create the worker thread
LeaveCriticalSection(&cs);//Let the thread work
EnterCriticalSection(&cs);//When we get control again (best case we get it next) connection will be initialised and n2i will hold its id
LeaveCriticalSection(&cs);//Make sure we dont lock
return n2i;//Return id
...
//in the thread main func
EnterCriticalSection(&cs);
//init connection, set an id
//set n2i to the same id
LeaveCriticalSection(&cs);
...


___
SOLVED


Debug output from my program (MT is main thread(creator), timespamps are from my logging utility):

[MT]Trying to EnterCriticalSection
[MT]Thread created, trying to LeaveCriticalSection
[MT]Waiting for child thread
[1]Trying to EnterCriticalSection
[MT]Returning...
[000:00:00:006]: Connection:-842150451
[1]Connection created: 594102, leaving cs
[000:00:00:009]: New connection!(594102)


As you can see main thread func gets control - returns as soon as it requests. The solution was to let the child thread get control:

1
2
3
4
5
while(n2i!=0){//Null is not an valid id, I use it for signaling : )
		Sleep(1);
		EnterCriticalSection(&cs);//When we get control again (best case we get it next) connection will be initialised
		LeaveCriticalSection(&cs);//Make sure we dont lock
	}

Last edited on
You need to instatiate a CRITICAL_SECTION, then initialise it before use.

You can then aquire/release it in threads.

When you're done, you uninitialise it.

Do this once:
1
2
3
4
CRITICAL_SECTION cs;
InitialCriticalSection(&cs);
...
DeleteCriticalSection(&cs);


Use this whenever you need to lock a section of code.
1
2
3
EnterCriticalSection(&cs);
...
LeaveCriticalSection(&cs);
I do have an initialize code, but I call DeleteCriticalSection on cleanup. It's my understanding this is the way it is supposed to be done.
CRITICAL_SECTION* cs;
??? why do a pointer do an critical section?...

then u need to access it by "cs" only and not "&cs"
Last edited on
Thanks for the replies

Is that all that could be wrong? I wrote this code from scratch so i dunno if that's the case in the program...i cant acess it now, but i know it compiles fine

this prolly is not whats wrong


PS: I've run several threads putting them to sleep in the lock, other threads waited fine. As it seems the only thing not working is
EnterCS...
LeaveCS//wait for completion
EnterCS
LeaveCs
return

___
Edited to fit program code
Last edited on
hmm... for intereset: may u show us the complete part of waht was not working?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
map<int, CONNECTION>		connections;
volatile CONNECTION*		n2i;
CRITICAL_SECTION			cs;

DWORD WINAPI _worker_listener_rel( void* in ){
	lrc++;
	EnterCriticalSection(&cs);
	if(!n2i)
		return 0;
	CONNECTION*	c	= (CONNECTION*)n2i;//Make a working pointer
	LPWSTR wndname	= (LPWSTR)malloc(124);
	wsprintfW(wndname, L"RELIABLE_LISTENER#%u", lrc);
	c->wnd = CreateWindowEx(NULL,
                          L"NETRELLISTENERCLS",
                          wndname, 
                          WS_OVERLAPPEDWINDOW, 
                          300,
                          300,
                          500, 
                          400, 
                          NULL,
                          NULL, 
                          appinst, 
                          NULL);
	if(!c->wnd){
		ONERR(0, 0, (*c));
		return 0;
	}
	n2i			= 0;
	LeaveCriticalSection(&cs);
	int result;
	c->sock	= socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	if(c->sock==INVALID_SOCKET){
		ONERR( (int)c->wnd, WSAGetLastError(), (*c));
		return 0;
	};
	connections.insert(pair<int, CONNECTION>((int)c->wnd, *c));//Make a copy
	WSAAsyncSelect(c->sock,c->wnd, WM_WSAASYNC, FD_READ | FD_ACCEPT | FD_CLOSE );
	//Bind and listen
	result	= bind(c->sock, (SOCKADDR*) &c->addr, sizeof(c->addr));
	if(result==SOCKET_ERROR){
		ONERR( (int)c->wnd, WSAGetLastError(), (*c));
		return 0;
	}
	result	= listen(c->sock, SOMAXCONN);
	if(result==SOCKET_ERROR){
		ONERR( (int)c->wnd, WSAGetLastError(), (*c));
		return 0;
	}
	ONINIT( (int)c->wnd, (*c) );
	MSG msg;
    while(GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
		if(msg.message==WM_KILLCONNECTION||msg.message==WM_QUIT){
			break;
		}
		DispatchMessage(&msg);
    }
	//Clean self and all subconns
	connections.erase((int)c->wnd);
	return 1;
}

int listener(unsigned short port, char flags, DATAFP onrecv, GENERALFP oninit, GENERALFP onshutdown, ERRORFP onerr){
	if(!inited){
		lasterr = 0;
		return 0;
	}
	CONNECTION* server				= new CONNECTION;
	server->onrecv					= onrecv;//If this is null than we'll only do sending
	server->oninit					= oninit;
	server->onshutdown				= onshutdown;
	server->onerror					= onerr;
	server->flags					= flags;

	server->pv.a					= (int*)malloc(sizeof(int)*participants_alloc);
	server->pv.pm					= participants_alloc;
	server->pv.pc					= 0;
	
	EnterCriticalSection(&cs);
	n2i								= server;

	server->addr.sin_family			= AF_INET;
	server->addr.sin_port			= htons( port );
	server->addr.sin_addr.s_addr	= inet_addr( "0.0.0.0" );
	server->latency					= -1;//Not connected

	server->thread					= CreateThread(	NULL, 0,
			(LPTHREAD_START_ROUTINE)(flags&LF_RELIABLE||flags&(!LF_RELIABLE|!LF_TIMECRIT))?_worker_listener_rel:_worker_listener_tc,
			(LPVOID)NULL, 0, &(server->tid));
	if(server->thread==NULL){
		n2i		= 0;
		LeaveCriticalSection(&cs);
		lasterr	= GetLastError();
		return 0;
	}
	LeaveCriticalSection(&cs);//Let the thread work;
	EnterCriticalSection(&cs);//When we get control again (best case we get it next) connection will be initialised
	LeaveCriticalSection(&cs);//Make sure we dont lock
/*Solution
while(n2i!=0){
		Sleep(1);
		EnterCriticalSection(&cs);//When we get control again (best case we get it next) connection will be initialised
		LeaveCriticalSection(&cs);//Make sure we dont lock
	}
	return (int)server->wnd;  //And return!
} */


It's a bit difrent, but no major changes. As I sed, the listener func got control right after it released it, making initialization imposible for the worker thread. It returned prematurly.

Hope it helps sum1
Last edited on
If CreateWindow fails, the critical section is never released.
Topic archived. No new replies allowed.