9 # include <arpa/inet.h>
10 # include <sys/types.h>
17 #if defined(TLP) || defined(DFPN_CLIENT)
19 lock_init( lock_t *plock )
21 # if defined(_MSC_VER)
23 # elif defined(__GNUC__) && ( defined(__i386__) || defined(__x86_64__) )
26 if ( pthread_mutex_init( plock, 0 ) )
28 str_error = "pthread_mutex_init() failed.";
37 lock_free( lock_t *plock )
39 # if defined(_MSC_VER)
41 # elif defined(__GNUC__) && ( defined(__i386__) || defined(__x86_64__) )
44 if ( pthread_mutex_destroy( plock ) )
46 str_error = "pthread_mutex_destroy() failed.";
55 unlock( lock_t *plock )
57 # if defined(_MSC_VER)
59 # elif defined(__GNUC__) && ( defined(__i386__) || defined(__x86_64__) )
62 pthread_mutex_unlock( plock );
70 # if defined(_MSC_VER)
71 while ( _InterlockedExchange( (void *)plock, 1 ) )
73 while ( *plock ) { tlp_yield();}
75 # elif defined(__GNUC__) && ( defined(__i386__) || defined(__x86_64__) )
80 asm ( "1: movl $1, %1 \n\t"
81 " xchgl (%0), %1 \n\t"
82 : "=g" (plock), "=r" (itemp) : "0" (plock) );
83 if ( ! itemp ) { return; }
84 while ( *plock ) { tlp_yield();}
87 pthread_mutex_lock( plock );
101 #endif /* TLP || DFPN_CLIENT */
104 #if defined(DFPN_CLIENT)
106 static int CONV proce_line( char *line_buf );
108 static unsigned int __stdcall dfpn_client_receiver( void *arg );
110 static void *dfpn_client_receiver( void *arg );
114 dfpn_client_start( const tree_t * restrict ptree )
116 if ( root_turn != min_posi_no_handicap.turn_to_move
117 || HAND_B != min_posi_no_handicap.hand_black
118 || HAND_W != min_posi_no_handicap.hand_white
119 || memcmp( BOARD, min_posi_no_handicap.asquare, nsquare ) )
121 sckt_shutdown( dfpn_client_sckt );
122 dfpn_client_sckt = SCKT_NULL;
126 if ( dfpn_client_sckt != SCKT_NULL ) { return; }
127 if ( dfpn_client_str_addr[0] == '\0' ) { return; }
129 dfpn_client_sckt = sckt_connect( dfpn_client_str_addr, dfpn_client_port );
130 if ( dfpn_client_sckt == SCKT_NULL )
132 out_warning( "Connection to DFPN server failed." );
136 Out( "New connection to DFPN server: %s %d\n",
137 dfpn_client_str_addr, dfpn_client_port );
141 if ( ! _beginthreadex( 0, 0, &dfpn_client_receiver, NULL, 0, 0 ) )
143 sckt_shutdown( dfpn_client_sckt );
144 dfpn_client_sckt = SCKT_NULL;
145 out_warning( "_beginthreadex() failed." );
150 if ( pthread_create( &pt, &pthread_attr, &dfpn_client_receiver, NULL ) )
152 sckt_shutdown( dfpn_client_sckt );
153 dfpn_client_sckt = SCKT_NULL;
154 out_warning( "_beginthreadex() failed." );
159 dfpn_client_out( "Client: anonymous\n" );
163 # if defined(_MSC_VER)
164 # pragma warning(disable:4100)
165 # elif defined(__ICC)
166 # pragma warning(disable:869)
169 # if defined(_MSC_VER)
170 static unsigned int __stdcall dfpn_client_receiver( void *arg )
172 static void *dfpn_client_receiver( void *arg )
175 #define SIZE_RECV_BUF ( 1024 * 16 )
176 #define SIZE_LINE_BUF 1024
177 char recv_buf[ SIZE_RECV_BUF ];
178 char line_buf[ SIZE_LINE_BUF ];
179 char *str_end, *str_line_end;
193 tv.tv_sec = SEC_KEEP_ALIVE;
196 # if defined(_MSC_VER)
197 # pragma warning(disable:4127)
199 FD_SET( dfpn_client_sckt, &readfds );
200 # if defined(_MSC_VER)
201 # pragma warning(default:4127)
204 iret = select( (int)dfpn_client_sckt+1, &readfds, NULL, NULL, &tv );
205 if ( iret == SOCKET_ERROR )
207 out_warning( "%s", str_error );
208 goto dfpn_client_receiver_shutdown;
211 /* message arrived */
212 if ( iret ) { break; }
214 /* timeout and keepalive */
215 lock( &dfpn_client_lock);
216 iret = dfpn_client_out( "ping\n" );
217 unlock( &dfpn_client_lock);
218 if ( iret < 0 ) { return 0; }
222 len_recv_buf = (int)strlen( recv_buf );
223 str_end = recv_buf + len_recv_buf;
225 iret = recv( dfpn_client_sckt, str_end, SIZE_RECV_BUF-1-len_recv_buf, 0 );
226 if ( iret == SOCKET_ERROR )
228 str_error = str_WSAError( "recv() failed:" );
229 out_warning( "%s", str_error );
230 goto dfpn_client_receiver_shutdown;
232 if ( ! iret ) { goto dfpn_client_receiver_shutdown; }
233 recv_buf[ len_recv_buf + iret ] = '\0';
236 lock( &dfpn_client_lock );
239 str_line_end = strchr( recv_buf, '\n' );
240 if ( str_line_end == NULL )
242 if ( iret + len_recv_buf + 1 >= SIZE_RECV_BUF )
244 unlock( &dfpn_client_lock );
245 out_warning( "%s", str_ovrflw_line );
246 goto dfpn_client_receiver_shutdown;
251 size = str_line_end - recv_buf;
252 if ( size + 1 >= SIZE_LINE_BUF )
254 unlock( &dfpn_client_lock );
255 out_warning( "%s", str_ovrflw_line );
256 goto dfpn_client_receiver_shutdown;
259 memcpy( line_buf, recv_buf, size );
260 memmove( recv_buf, str_line_end+1, strlen(str_line_end+1) + 1 );
262 line_buf[size] = '\0';
264 if ( proce_line( line_buf ) < 0 )
266 unlock( &dfpn_client_lock );
267 out_warning( "invalid messages from DFPN server" );
268 goto dfpn_client_receiver_shutdown;
271 unlock( &dfpn_client_lock );
274 dfpn_client_receiver_shutdown:
275 sckt_shutdown( dfpn_client_sckt );
276 dfpn_client_sckt = SCKT_NULL;
277 out_warning( "A connection to DFPN server is down." );
281 # if defined(_MSC_VER)
282 # pragma warning(default:4100)
283 # elif defined(__ICC)
284 # pragma warning(default:869)
288 static int CONV proce_line( char *line_buf )
291 volatile dfpn_client_cresult_t *pcresult;
294 token = strtok_r( line_buf, str_delimiters, &last );
295 if ( token == NULL ) { return -1; }
297 /* check signature */
298 if ( strcmp( token, (const char *)dfpn_client_signature ) ) { return 1; }
300 token = strtok_r( NULL, str_delimiters, &last );
301 if ( token == NULL ) { return -1; }
304 if ( ! strcmp( token, "WIN" ) )
306 token = strtok_r( NULL, str_delimiters, &last );
307 if ( token == NULL || ! is_move( token ) ) { return -1; }
308 dfpn_client_rresult = dfpn_client_win;
309 dfpn_client_flag_read = 1;
310 memcpy( (char *)dfpn_client_str_move, token, 7 );
314 if ( ! strcmp( token, "LOSE" ) )
316 dfpn_client_rresult = dfpn_client_lose;
317 dfpn_client_flag_read = 1;
321 if ( ! strcmp( token, "UNSOLVED" ) )
323 dfpn_client_rresult = dfpn_client_misc;
324 dfpn_client_flag_read = 1;
329 if ( ! is_move( token ) ) { return -1; }
330 if ( MAX_LEGAL_MOVES <= dfpn_client_num_cresult ) { return -1; }
331 pcresult = &dfpn_client_cresult[dfpn_client_num_cresult];
332 memcpy( (char *)pcresult->str_move, token, 7 );
334 token = strtok_r( NULL, str_delimiters, &last );
335 if ( token == NULL ) { return -1; }
337 if ( ! strcmp( token, "WIN" ) )
339 pcresult->result = dfpn_client_win;
340 dfpn_client_flag_read = 1;
341 dfpn_client_num_cresult += 1;
345 if ( ! strcmp( token, "LOSE" ) )
347 pcresult->result = dfpn_client_lose;
348 dfpn_client_flag_read = 1;
349 dfpn_client_num_cresult += 1;
353 if ( ! strcmp( token, "UNSOLVED" ) )
355 pcresult->result = dfpn_client_misc;
356 dfpn_client_flag_read = 1;
357 dfpn_client_num_cresult += 1;
364 #endif /* DFPN_CLINET */
370 static unsigned int __stdcall start_address( void *arg );
372 static void *start_address( void *arg );
375 static tree_t *find_child( void );
376 static void init_state( const tree_t * restrict parent,
377 tree_t * restrict child );
378 static void copy_state( tree_t * restrict parent,
379 const tree_t * restrict child, int value );
380 static void wait_work( int tid, tree_t *parent );
385 int work[ TLP_MAX_THREADS ];
388 if ( tlp_num ) { return 1; }
390 for ( num = 1; num < tlp_max; num++ )
395 if ( ! _beginthreadex( 0, 0, start_address, work+num, 0, 0 ) )
397 str_error = "_beginthreadex() failed.";
403 if ( pthread_create( &pt, &pthread_attr, start_address, work+num ) )
405 str_error = "pthread_create() failed.";
411 while ( tlp_num +1 < tlp_max ) { tlp_yield(); }
421 while ( tlp_num ) { tlp_yield(); }
427 tlp_split( tree_t * restrict ptree )
434 if ( ! tlp_idle || ptree->tlp_abort )
440 tlp_ptrees[ ptree->tlp_id ] = NULL;
441 ptree->tlp_nsibling = 0;
443 for ( num = 0; num < tlp_max; num++ )
445 if ( tlp_ptrees[num] ) { ptree->tlp_ptrees_sibling[num] = 0; }
447 child = find_child();
448 if ( ! child ) { continue; }
452 for ( i=0; i<tlp_max; i++ ) { child->tlp_ptrees_sibling[i] = NULL; }
453 child->tlp_ptree_parent = ptree;
454 child->tlp_id = (unsigned char)num;
456 child->tlp_abort = 0;
457 ptree->tlp_ptrees_sibling[num] = child;
458 ptree->tlp_nsibling += 1;
459 init_state( ptree, child );
461 tlp_ptrees[num] = child;
467 tlp_ptrees[ ptree->tlp_id ] = ptree;
477 wait_work( ptree->tlp_id, ptree );
484 tlp_set_abort( tree_t * restrict ptree )
488 ptree->tlp_abort = 1;
489 for ( num = 0; num < tlp_max; num++ )
490 if ( ptree->tlp_ptrees_sibling[num] )
492 tlp_set_abort( ptree->tlp_ptrees_sibling[num] );
497 #if defined(MNJ_LAN) || defined(USI)
499 tlp_count_node( tree_t * restrict ptree )
501 uint64_t uret = ptree->node_searched;
504 for ( num = 0; num < tlp_max; num++ )
505 if ( ptree->tlp_ptrees_sibling[num] )
507 uret += tlp_count_node( ptree->tlp_ptrees_sibling[num] );
516 tlp_is_descendant( const tree_t * restrict ptree, int slot_ancestor )
518 int slot = (int)ptree->tlp_slot;
521 if ( slot == slot_ancestor ) { return 1; }
522 else if ( ! slot ) { return 0; }
523 else { slot = tlp_atree_work[slot].tlp_ptree_parent->tlp_slot; }
528 # if defined(_MSC_VER)
529 static unsigned int __stdcall start_address( void *arg )
531 static void *start_address( void *arg )
534 int tid = *(int *)arg;
536 tlp_ptrees[tid] = NULL;
539 Out( "Hi from thread no.%d\n", tid );
544 wait_work( tid, NULL );
547 Out( "Bye from thread no.%d\n", tid );
557 wait_work( int tid, tree_t *parent )
565 if ( tlp_ptrees[tid] ) { break; }
566 if ( parent && ! parent->tlp_nsibling ) { break; }
567 if ( tlp_abort ) { return; }
573 if ( ! tlp_ptrees[tid] ) { tlp_ptrees[tid] = parent; }
577 slot = tlp_ptrees[tid];
578 if ( slot == parent ) { return; }
580 value = tlp_search( slot,
581 slot->tlp_ptree_parent->tlp_best,
582 slot->tlp_ptree_parent->tlp_beta,
583 slot->tlp_ptree_parent->tlp_turn,
584 slot->tlp_ptree_parent->tlp_depth,
585 slot->tlp_ptree_parent->tlp_ply,
586 slot->tlp_ptree_parent->tlp_state_node );
589 copy_state( slot->tlp_ptree_parent, slot, value );
590 slot->tlp_ptree_parent->tlp_nsibling -= 1;
591 slot->tlp_ptree_parent->tlp_ptrees_sibling[tid] = NULL;
593 tlp_ptrees[tid] = NULL;
605 for ( i = 1; i < TLP_NUM_WORK && tlp_atree_work[i].tlp_used; i++ );
606 if ( i == TLP_NUM_WORK ) { return NULL; }
607 if ( i > tlp_nslot ) { tlp_nslot = i; }
609 return tlp_atree_work + i;
614 init_state( const tree_t * restrict parent, tree_t * restrict child )
618 child->posi = parent->posi;
619 child->node_searched = 0;
620 child->null_pruning_done = 0;
621 child->null_pruning_tried = 0;
622 child->check_extension_done = 0;
623 child->recap_extension_done = 0;
624 child->onerp_extension_done = 0;
625 child->neval_called = 0;
626 child->nquies_called = 0;
627 child->nfour_fold_rep = 0;
628 child->nperpetual_check = 0;
629 child->nsuperior_rep = 0;
630 child->nrep_tried = 0;
631 child->ntrans_always_hit = 0;
632 child->ntrans_prefer_hit = 0;
633 child->ntrans_probe = 0;
634 child->ntrans_exact = 0;
635 child->ntrans_lower = 0;
636 child->ntrans_upper = 0;
637 child->ntrans_superior_hit = 0;
638 child->ntrans_inferior_hit = 0;
639 child->fail_high = 0;
640 child->fail_high_first = 0;
641 ply = parent->tlp_ply;
643 child->anext_move[ply].value_cap1 = parent->anext_move[ply].value_cap1;
644 child->anext_move[ply].value_cap2 = parent->anext_move[ply].value_cap2;
645 child->anext_move[ply].move_cap1 = parent->anext_move[ply].move_cap1;
646 child->anext_move[ply].move_cap2 = parent->anext_move[ply].move_cap2;
648 child->move_last[ply] = child->amove;
649 child->save_eval[ply] = parent->save_eval[ply];
650 child->current_move[ply-1] = parent->current_move[ply-1];
651 child->nsuc_check[ply-1] = parent->nsuc_check[ply-1];
652 child->nsuc_check[ply] = parent->nsuc_check[ply];
653 child->nrep = parent->nrep;
655 memcpy( child->hist_good, parent->hist_good, sizeof(parent->hist_good) );
656 memcpy( child->hist_tried, parent->hist_tried, sizeof(parent->hist_tried) );
658 for ( i = 0; i < child->nrep + ply - 1; i++ )
660 child->rep_board_list[i] = parent->rep_board_list[i];
661 child->rep_hand_list[i] = parent->rep_hand_list[i];
663 for ( i = ply; i < PLY_MAX; i++ )
665 child->amove_killer[i] = parent->amove_killer[i];
666 child->killers[i] = parent->killers[i];
673 copy_state( tree_t * restrict parent, const tree_t * restrict child,
678 parent->check_extension_done += child->check_extension_done;
679 parent->recap_extension_done += child->recap_extension_done;
681 if ( ! child->node_searched ) { return; }
683 parent->node_searched += child->node_searched;
684 parent->null_pruning_done += child->null_pruning_done;
685 parent->null_pruning_tried += child->null_pruning_tried;
686 parent->onerp_extension_done += child->onerp_extension_done;
687 parent->neval_called += child->neval_called;
688 parent->nquies_called += child->nquies_called;
689 parent->nrep_tried += child->nrep_tried;
690 parent->nfour_fold_rep += child->nfour_fold_rep;
691 parent->nperpetual_check += child->nperpetual_check;
692 parent->nsuperior_rep += child->nsuperior_rep;
693 parent->ntrans_always_hit += child->ntrans_always_hit;
694 parent->ntrans_prefer_hit += child->ntrans_prefer_hit;
695 parent->ntrans_probe += child->ntrans_probe;
696 parent->ntrans_exact += child->ntrans_exact;
697 parent->ntrans_lower += child->ntrans_lower;
698 parent->ntrans_upper += child->ntrans_upper;
699 parent->ntrans_superior_hit += child->ntrans_superior_hit;
700 parent->ntrans_inferior_hit += child->ntrans_inferior_hit;
701 parent->fail_high_first += child->fail_high_first;
702 parent->fail_high += child->fail_high;
704 if ( child->tlp_abort || value <= parent->tlp_best ) { return; }
706 ply = parent->tlp_ply;
707 parent->tlp_best = (short)value;
708 parent->pv[ply] = child->pv[ply];
710 lock( &parent->tlp_lock );
711 parent->current_move[ply] = child->current_move[ply];
712 memcpy( parent->hist_tried, child->hist_tried, sizeof(child->hist_tried) );
713 memcpy( parent->hist_good, child->hist_good, sizeof(child->hist_good) );
714 for ( i = ply; i < PLY_MAX; i++ )
716 parent->amove_killer[i] = child->amove_killer[i];
717 parent->killers[i] = child->killers[i];
719 unlock( &parent->tlp_lock );