a geicko-2 based round robin ranking system designed to test c++ battleship submissions battleship.dunkirk.sh
at main 2.0 kB view raw
1// Copyright (C) 2019 Yasuhiro Matsumoto <mattn.jp@gmail.com>. 2// 3// Use of this source code is governed by an MIT-style 4// license that can be found in the LICENSE file. 5 6//go:build cgo && sqlite_unlock_notify 7// +build cgo,sqlite_unlock_notify 8 9package sqlite3 10 11/* 12#cgo CFLAGS: -DSQLITE_ENABLE_UNLOCK_NOTIFY 13 14#include <stdlib.h> 15#ifndef USE_LIBSQLITE3 16#include "sqlite3-binding.h" 17#else 18#include <sqlite3.h> 19#endif 20 21extern void unlock_notify_callback(void *arg, int argc); 22*/ 23import "C" 24import ( 25 "fmt" 26 "math" 27 "sync" 28 "unsafe" 29) 30 31type unlock_notify_table struct { 32 sync.Mutex 33 seqnum uint 34 table map[uint]chan struct{} 35} 36 37var unt unlock_notify_table = unlock_notify_table{table: make(map[uint]chan struct{})} 38 39func (t *unlock_notify_table) add(c chan struct{}) uint { 40 t.Lock() 41 defer t.Unlock() 42 h := t.seqnum 43 t.table[h] = c 44 t.seqnum++ 45 return h 46} 47 48func (t *unlock_notify_table) remove(h uint) { 49 t.Lock() 50 defer t.Unlock() 51 delete(t.table, h) 52} 53 54func (t *unlock_notify_table) get(h uint) chan struct{} { 55 t.Lock() 56 defer t.Unlock() 57 c, ok := t.table[h] 58 if !ok { 59 panic(fmt.Sprintf("Non-existent key for unlcok-notify channel: %d", h)) 60 } 61 return c 62} 63 64//export unlock_notify_callback 65func unlock_notify_callback(argv unsafe.Pointer, argc C.int) { 66 for i := 0; i < int(argc); i++ { 67 parg := ((*(*[(math.MaxInt32 - 1) / unsafe.Sizeof((*C.uint)(nil))]*[1]uint)(argv))[i]) 68 arg := *parg 69 h := arg[0] 70 c := unt.get(h) 71 c <- struct{}{} 72 } 73} 74 75//export unlock_notify_wait 76func unlock_notify_wait(db *C.sqlite3) C.int { 77 // It has to be a bufferred channel to not block in sqlite_unlock_notify 78 // as sqlite_unlock_notify could invoke the callback before it returns. 79 c := make(chan struct{}, 1) 80 defer close(c) 81 82 h := unt.add(c) 83 defer unt.remove(h) 84 85 pargv := C.malloc(C.sizeof_uint) 86 defer C.free(pargv) 87 88 argv := (*[1]uint)(pargv) 89 argv[0] = h 90 if rv := C.sqlite3_unlock_notify(db, (*[0]byte)(C.unlock_notify_callback), unsafe.Pointer(pargv)); rv != C.SQLITE_OK { 91 return rv 92 } 93 94 <-c 95 96 return C.SQLITE_OK 97}