From 3ba5b6536e730baf01efb3203be280c3e61319bd Mon Sep 17 00:00:00 2001 From: Determinant Date: Sun, 16 Jun 2019 23:27:05 -0400 Subject: eliminate the use of Free() --- event.go | 113 ++++++++++++++++++++++------- msg.go | 20 ++++-- netaddr.go | 51 ++++++++----- network.go | 185 ++++++++++++++++++++++++++++++++++-------------- salticidae | 2 +- stream.go | 118 +++++++++++++++++++----------- test_msgnet/main.go | 41 ++++------- test_p2p_stress/main.go | 60 ++++++---------- 8 files changed, 381 insertions(+), 209 deletions(-) diff --git a/event.go b/event.go index 1c8a94e..7ebc643 100644 --- a/event.go +++ b/event.go @@ -3,50 +3,115 @@ package salticidae // #include "salticidae/event.h" // #include import "C" +import "runtime" -type EventContext = *C.struct_eventcontext_t +type CEventContext = *C.eventcontext_t +type eventContext struct { + inner CEventContext + attached map[uintptr]interface{} +} +type EventContext = *eventContext + +func NewEventContext() EventContext { + res := &eventContext{ + inner: C.eventcontext_new(), + attached: make(map[uintptr]interface{}), + } + runtime.SetFinalizer(res, func(self EventContext) { self.free() }) + return res +} + +func (self EventContext) attach(ptr rawptr_t, x interface{}) { self.attached[uintptr(ptr)] = x } +func (self EventContext) detach(ptr rawptr_t) { delete(self.attached, uintptr(ptr)) } +func (self EventContext) free() { C.eventcontext_free(self.inner) } +func (self EventContext) Dispatch() { C.eventcontext_dispatch(self.inner) } +func (self EventContext) Stop() { C.eventcontext_stop(self.inner) } -func NewEventContext() EventContext { return C.eventcontext_new() } -func (self EventContext) Free() { C.eventcontext_free(self) } -func (self EventContext) Dispatch() { C.eventcontext_dispatch(self) } -func (self EventContext) Stop() { C.eventcontext_stop(self) } +type CThreadCall = *C.threadcall_t +type threadCall struct { inner CThreadCall } +type ThreadCall = *threadCall -type ThreadCall = *C.struct_threadcall_t type ThreadCallCallback = C.threadcall_callback_t -func NewThreadCall(ec EventContext) ThreadCall { return C.threadcall_new(ec) } +func NewThreadCall(ec EventContext) ThreadCall { + res := &threadCall{ inner: C.threadcall_new(ec.inner) } + runtime.SetFinalizer(res, func(self ThreadCall) { self.free() }) + return res +} -func (self ThreadCall) Free() { C.threadcall_free(self) } +func (self ThreadCall) free() { C.threadcall_free(self.inner) } func (self ThreadCall) AsyncCall(callback ThreadCallCallback, userdata rawptr_t) { - C.threadcall_async_call(self, callback, userdata) + C.threadcall_async_call(self.inner, callback, userdata) } -func (self ThreadCall) GetEC() EventContext { return C.threadcall_get_ec(self) } +type CTimerEvent = *C.timerev_t +type timerEvent struct { + inner CTimerEvent + ec EventContext +} +type TimerEvent = *timerEvent -type TimerEvent = *C.timerev_t type TimerEventCallback = C.timerev_callback_t -func NewTimerEvent(ec EventContext, cb TimerEventCallback, userdata rawptr_t) TimerEvent { - return C.timerev_new(ec, cb, userdata) +func NewTimerEvent(_ec EventContext, cb TimerEventCallback, userdata rawptr_t) TimerEvent { + res := &timerEvent{ + inner: C.timerev_new(_ec.inner, cb, userdata), + ec: _ec, + } + _ec.attach(rawptr_t(res.inner), res) + runtime.SetFinalizer(res, func(self TimerEvent) { self.free() }) + return res } -func (self TimerEvent) Free() { C.timerev_free(self) } +func (self TimerEvent) free() { C.timerev_free(self.inner) } func (self TimerEvent) SetCallback(callback TimerEventCallback, userdata rawptr_t) { - C.timerev_set_callback(self, callback, userdata) + C.timerev_set_callback(self.inner, callback, userdata) } -func (self TimerEvent) Add(t_sec float64) { C.timerev_add(self, C.double(t_sec)) } -func (self TimerEvent) Clear() { C.timerev_clear(self) } +func (self TimerEvent) Add(t_sec float64) { C.timerev_add(self.inner, C.double(t_sec)) } +func (self TimerEvent) Del() { + self.ec.detach(rawptr_t(self.inner)) + C.timerev_del(self.inner) +} + +func (self TimerEvent) Clear() { + self.ec.detach(rawptr_t(self.inner)) + C.timerev_clear(self.inner) +} + +type CSigEvent = *C.sigev_t +type sigEvent struct { + inner CSigEvent + ec EventContext +} +type SigEvent = *sigEvent -type SigEvent = *C.sigev_t type SigEventCallback = C.sigev_callback_t -var SIGTERM = C.SIGTERM -var SIGINT = C.SIGINT -func NewSigEvent(ec EventContext, cb SigEventCallback, userdata rawptr_t) SigEvent { - return C.sigev_new(ec, cb, userdata) +var ( + SIGTERM = C.SIGTERM + SIGINT = C.SIGINT +) + +func NewSigEvent(_ec EventContext, cb SigEventCallback, userdata rawptr_t) SigEvent { + res := &sigEvent{ + inner: C.sigev_new(_ec.inner, cb, userdata), + ec: _ec, + } + _ec.attach(rawptr_t(res.inner), res) + runtime.SetFinalizer(res, func(self SigEvent) { self.free() }) + return res } -func (self SigEvent) Add(sig int) { C.sigev_add(self, C.int(sig)) } -func (self SigEvent) Free() { C.sigev_free(self) } +func (self SigEvent) free() { C.sigev_free(self.inner) } +func (self SigEvent) Add(sig int) { C.sigev_add(self.inner, C.int(sig)) } +func (self SigEvent) Del() { + self.ec.detach(rawptr_t(self.inner)) + C.sigev_del(self.inner) +} + +func (self SigEvent) Clear() { + self.ec.detach(rawptr_t(self.inner)) + C.sigev_clear(self.inner) +} diff --git a/msg.go b/msg.go index c3c0811..eb02fc3 100644 --- a/msg.go +++ b/msg.go @@ -3,20 +3,28 @@ package salticidae // #include // #include "salticidae/msg.h" import "C" +import "runtime" -type Msg = *C.struct_msg_t +type CMsg = *C.struct_msg_t +type msg struct { inner CMsg } +type Msg = *msg + +func MsgFromC(ptr *C.struct_msg_t) Msg { return &msg{ inner: ptr } } func NewMsgMovedFromByteArray(opcode Opcode, _moved_payload ByteArray) Msg { - return C.msg_new_moved_from_bytearray(C._opcode_t(opcode), _moved_payload) + res := &msg{ inner: C.msg_new_moved_from_bytearray(C._opcode_t(opcode), _moved_payload.inner) } + runtime.SetFinalizer(res, func(self Msg) { self.free() }) + return res } -func (self Msg) Free() { C.msg_free(self) } +func (self Msg) free() { C.msg_free(self.inner) } func (self Msg) ConsumePayload() DataStream { - return C.msg_consume_payload(self) + res := &dataStream{ inner: C.msg_consume_payload(self.inner) } + runtime.SetFinalizer(res, func(self DataStream) { self.free() }) + return res } func (self Msg) GetOpcode() Opcode { - return Opcode(C.msg_get_opcode(self)) + return Opcode(C.msg_get_opcode(self.inner)) } - diff --git a/netaddr.go b/netaddr.go index a631689..ab261b5 100644 --- a/netaddr.go +++ b/netaddr.go @@ -3,33 +3,50 @@ package salticidae // #include // #include "salticidae/netaddr.h" import "C" +import "runtime" -type NetAddr = *C.netaddr_t -type NetAddrArray = *C.netaddr_array_t +type netAddr struct { + inner *C.netaddr_t +} + +type NetAddr = *netAddr + +type netAddrArray struct { + inner *C.netaddr_array_t +} + +type NetAddrArray = *netAddrArray func NewAddrFromIPPortString(addr string) (res NetAddr) { c_str := C.CString(addr) - res = C.netaddr_new_from_sipport(c_str) + res = &netAddr{ inner: C.netaddr_new_from_sipport(c_str) } C.free(rawptr_t(c_str)) + runtime.SetFinalizer(res, func(self NetAddr) { self.free() }) return } -func (self NetAddr) Free() { C.netaddr_free(self) } - -func (self NetAddr) IsEq(other NetAddr) bool { return bool(C.netaddr_is_eq(self, other)) } - -func (self NetAddr) IsNull() bool { return bool(C.netaddr_is_null(self)) } - -func (self NetAddr) GetIP() uint32 { return uint32(C.netaddr_get_ip(self)) } - -func (self NetAddr) GetPort() uint16 { return uint16(C.netaddr_get_port(self)) } - -func NewAddrArrayFromAddrs(arr []NetAddr) NetAddrArray { +func NewAddrArrayFromAddrs(arr []NetAddr) (res NetAddrArray) { size := len(arr) if size > 0 { - base := (**C.netaddr_t)(&arr[0]) - return C.netaddr_array_new_from_addrs(base, C.size_t(size)) + // FIXME: here we assume struct of a single pointer has the same memory + // footprint the pointer + base := (**C.netaddr_t)(rawptr_t(&arr[0])) + res = &netAddrArray{ inner: C.netaddr_array_new_from_addrs(base, C.size_t(size)) } } else { - return C.netaddr_array_new() + res = &netAddrArray{ inner: C.netaddr_array_new() } } + runtime.SetFinalizer(res, func(self NetAddrArray) { self.free() }) + return } + +func (self NetAddr) free() { C.netaddr_free(self.inner) } + +func (self NetAddr) IsEq(other NetAddr) bool { return bool(C.netaddr_is_eq(self.inner, other.inner)) } + +func (self NetAddr) IsNull() bool { return bool(C.netaddr_is_null(self.inner)) } + +func (self NetAddr) GetIP() uint32 { return uint32(C.netaddr_get_ip(self.inner)) } + +func (self NetAddr) GetPort() uint16 { return uint16(C.netaddr_get_port(self.inner)) } + +func (self NetAddrArray) free() { C.netaddr_array_free(self.inner) } diff --git a/network.go b/network.go index d4d85cd..fdc513b 100644 --- a/network.go +++ b/network.go @@ -2,16 +2,30 @@ package salticidae // #include "salticidae/network.h" import "C" +import "runtime" -type MsgNetwork = *C.struct_msgnetwork_t +type CMsgNetwork = *C.msgnetwork_t +type msgNetwork struct { inner CMsgNetwork } +type MsgNetwork = *msgNetwork -type MsgNetworkConn = *C.struct_msgnetwork_conn_t +func MsgNetworkFromC(ptr CMsgNetwork) MsgNetwork { + return &msgNetwork{ inner: ptr } +} + +type CMsgNetworkConn = *C.msgnetwork_conn_t +type msgNetworkConn struct { inner CMsgNetworkConn } +type MsgNetworkConn = *msgNetworkConn + +func MsgNetworkConnFromC(ptr CMsgNetworkConn) MsgNetworkConn { + return &msgNetworkConn{ inner: ptr } +} type MsgNetworkConnMode = C.msgnetwork_conn_mode_t +func (self MsgNetworkConn) free() { C.msgnetwork_conn_free(self.inner) } func (self MsgNetworkConn) GetNet() MsgNetwork { - return C.msgnetwork_conn_get_net(self) + return &msgNetwork{ inner: C.msgnetwork_conn_get_net(self.inner) } } var ( @@ -21,77 +35,115 @@ var ( ) func (self MsgNetworkConn) GetMode() MsgNetworkConnMode { - return C.msgnetwork_conn_get_mode(self) + return C.msgnetwork_conn_get_mode(self.inner) } func (self MsgNetworkConn) GetAddr() NetAddr { - return C.msgnetwork_conn_get_addr(self) + res := &netAddr{ inner: C.msgnetwork_conn_get_addr(self.inner) } + runtime.SetFinalizer(res, func(self NetAddr) { self.free() }) + return res } -type MsgNetworkConfig = *C.struct_msgnetwork_config_t +type CMsgNetworkConfig = *C.msgnetwork_config_t +type msgNetworkConfig struct { inner CMsgNetworkConfig } +type MsgNetworkConfig = *msgNetworkConfig -func NewMsgNetworkConfig() MsgNetworkConfig { return C.msgnetwork_config_new() } +func MsgNetworkConfigFromC(ptr CMsgNetworkConfig) MsgNetworkConfig { + return &msgNetworkConfig{ inner: ptr } +} + +func NewMsgNetworkConfig() MsgNetworkConfig { + res := &msgNetworkConfig{ inner: C.msgnetwork_config_new() } + runtime.SetFinalizer(res, func(self MsgNetworkConfig) { self.free() }) + return res +} -func (self MsgNetworkConfig) Free() { C.msgnetwork_config_free(self) } +func (self MsgNetworkConfig) free() { C.msgnetwork_config_free(self.inner) } func (self MsgNetworkConfig) BurstSize(size int) { - C.msgnetwork_config_burst_size(self, C.size_t(size)) + C.msgnetwork_config_burst_size(self.inner, C.size_t(size)) } func (self MsgNetworkConfig) MaxListenBacklog(backlog int) { - C.msgnetwork_config_max_listen_backlog(self, C.int(backlog)) + C.msgnetwork_config_max_listen_backlog(self.inner, C.int(backlog)) } func (self MsgNetworkConfig) ConnServerTimeout(timeout float64) { - C.msgnetwork_config_conn_server_timeout(self, C.double(timeout)) + C.msgnetwork_config_conn_server_timeout(self.inner, C.double(timeout)) } func (self MsgNetworkConfig) SegBuffSize(size int) { - C.msgnetwork_config_seg_buff_size(self, C.size_t(size)) + C.msgnetwork_config_seg_buff_size(self.inner, C.size_t(size)) } func (self MsgNetworkConfig) NWorker(nworker int) { - C.msgnetwork_config_nworker(self, C.size_t(nworker)) + C.msgnetwork_config_nworker(self.inner, C.size_t(nworker)) } func (self MsgNetworkConfig) QueueCapacity(capacity int) { - C.msgnetwork_config_queue_capacity(self, C.size_t(capacity)) + C.msgnetwork_config_queue_capacity(self.inner, C.size_t(capacity)) } func NewMsgNetwork(ec EventContext, config MsgNetworkConfig) MsgNetwork { - return C.msgnetwork_new(ec, config) + res := &msgNetwork { inner: C.msgnetwork_new(ec.inner, config.inner) } + ec.attach(rawptr_t(res.inner), res) + runtime.SetFinalizer(res, func(self MsgNetwork) { self.free() }) + return res } -func (self MsgNetwork) Free() { C.msgnetwork_free(self) } -func (self MsgNetwork) Listen(addr NetAddr, err *Error) { C.msgnetwork_listen(self, addr, err) } -func (self MsgNetwork) Start() { C.msgnetwork_start(self) } - -func (self MsgNetwork) SendMsgByMove(msg Msg, conn MsgNetworkConn) { C.msgnetwork_send_msg_by_move(self, msg, conn) } -func (self MsgNetwork) Connect(addr NetAddr, err *Error) MsgNetworkConn { return C.msgnetwork_connect(self, addr, err) } -func (self MsgNetwork) Terminate(conn MsgNetworkConn) { C.msgnetwork_terminate(self, conn) } +func (self MsgNetwork) free() { C.msgnetwork_free(self.inner) } +func (self MsgNetwork) Listen(addr NetAddr, err *Error) { C.msgnetwork_listen(self.inner, addr.inner, err) } +func (self MsgNetwork) Start() { C.msgnetwork_start(self.inner) } -func (self MsgNetworkConn) Copy() MsgNetworkConn { return C.msgnetwork_conn_copy(self) } -func (self MsgNetworkConn) Free() { C.msgnetwork_conn_free(self) } +func (self MsgNetwork) SendMsgByMove(msg Msg, conn MsgNetworkConn) { C.msgnetwork_send_msg_by_move(self.inner, msg.inner, conn.inner) } +func (self MsgNetwork) Connect(addr NetAddr, err *Error) MsgNetworkConn { + res := &msgNetworkConn { inner: C.msgnetwork_connect(self.inner, addr.inner, err) } + runtime.SetFinalizer(res, func(self MsgNetworkConn) { self.free() }) + return res +} +func (self MsgNetwork) Terminate(conn MsgNetworkConn) { C.msgnetwork_terminate(self.inner, conn.inner) } -type MsgNetworkMsgCallback = C.msgnetwork_msg_callback_t -type MsgNetworkConnCallback = C.msgnetwork_conn_callback_t -type MsgNetworkErrorCallback = C.msgnetwork_error_callback_t func (self MsgNetwork) RegHandler(opcode Opcode, callback MsgNetworkMsgCallback, userdata rawptr_t) { - C.msgnetwork_reg_handler(self, C._opcode_t(opcode), callback, userdata) + C.msgnetwork_reg_handler(self.inner, C._opcode_t(opcode), callback, userdata) } func (self MsgNetwork) RegConnHandler(callback MsgNetworkConnCallback, userdata rawptr_t) { - C.msgnetwork_reg_conn_handler(self, callback, userdata) + C.msgnetwork_reg_conn_handler(self.inner, callback, userdata) } func (self MsgNetwork) RegErrorHandler(callback MsgNetworkErrorCallback, userdata rawptr_t) { - C.msgnetwork_reg_error_handler(self, callback, userdata) + C.msgnetwork_reg_error_handler(self.inner, callback, userdata) +} + + +func (self MsgNetworkConn) Copy() MsgNetworkConn { + res := &msgNetworkConn { inner: C.msgnetwork_conn_copy(self.inner) } + runtime.SetFinalizer(res, func(self MsgNetworkConn) { self.free() }) + return res +} +func (self MsgNetworkConn) Free() { C.msgnetwork_conn_free(self.inner) } + +type MsgNetworkMsgCallback = C.msgnetwork_msg_callback_t +type MsgNetworkConnCallback = C.msgnetwork_conn_callback_t +type MsgNetworkErrorCallback = C.msgnetwork_error_callback_t + +type CPeerNetwork = *C.peernetwork_t +type peerNetwork struct { inner CPeerNetwork } +type PeerNetwork = *peerNetwork + +func PeerNetworkFromC(ptr CPeerNetwork) PeerNetwork { + return &peerNetwork{ inner: ptr } } -type PeerNetwork = *C.struct_peernetwork_t -type PeerNetworkConn = *C.struct_peernetwork_conn_t +type CPeerNetworkConn = *C.peernetwork_conn_t +type peerNetworkConn struct { inner CPeerNetworkConn } +type PeerNetworkConn = *peerNetworkConn + +func PeerNetworkConnFromC(ptr CPeerNetworkConn) PeerNetworkConn { + return &peerNetworkConn{ inner: ptr } +} type PeerNetworkIdMode = C.peernetwork_id_mode_t @@ -100,57 +152,86 @@ var ( ID_MODE_IP_PORT_BASED = PeerNetworkIdMode(C.ID_MODE_IP_PORT_BASED) ) -type PeerNetworkConfig = *C.struct_peernetwork_config_t +type CPeerNetworkConfig = *C.peernetwork_config_t +type peerNetworkConfig struct { inner CPeerNetworkConfig } +type PeerNetworkConfig = *peerNetworkConfig -func NewPeerNetworkConfig() PeerNetworkConfig { return C.peernetwork_config_new() } +func PeerNetworkConfigFromC(ptr CPeerNetworkConfig) PeerNetworkConfig { + return &peerNetworkConfig{ inner: ptr } +} + +func NewPeerNetworkConfig() PeerNetworkConfig { + res := &peerNetworkConfig { inner: C.peernetwork_config_new() } + runtime.SetFinalizer(res, func(self PeerNetworkConfig) { self.free() }) + return res +} -func (self PeerNetworkConfig) Free() { C.peernetwork_config_free(self) } +func (self PeerNetworkConfig) free() { C.peernetwork_config_free(self.inner) } func (self PeerNetworkConfig) RetryConnDelay(t_sec float64) { - C.peernetwork_config_retry_conn_delay(self, C.double(t_sec)) + C.peernetwork_config_retry_conn_delay(self.inner, C.double(t_sec)) } func (self PeerNetworkConfig) PingPeriod(t_sec float64) { - C.peernetwork_config_ping_period(self, C.double(t_sec)) + C.peernetwork_config_ping_period(self.inner, C.double(t_sec)) } func (self PeerNetworkConfig) ConnTimeout(t_sec float64) { - C.peernetwork_config_conn_timeout(self, C.double(t_sec)) + C.peernetwork_config_conn_timeout(self.inner, C.double(t_sec)) } func (self PeerNetworkConfig) IdMode(mode PeerNetworkIdMode) { - C.peernetwork_config_id_mode(self, mode) + C.peernetwork_config_id_mode(self.inner, mode) } func (self PeerNetworkConfig) AsMsgNetworkConfig() MsgNetworkConfig { - return C.peernetwork_config_as_msgnetwork_config(self) + return &msgNetworkConfig { inner: C.peernetwork_config_as_msgnetwork_config(self.inner) } } func NewPeerNetwork(ec EventContext, config PeerNetworkConfig) PeerNetwork { - return C.peernetwork_new(ec, config) + res := &peerNetwork { inner: C.peernetwork_new(ec.inner, config.inner) } + ec.attach(rawptr_t(res.inner), res) + runtime.SetFinalizer(res, func(self PeerNetwork) { self.free() }) + return res } -func (self PeerNetwork) Free() { C.peernetwork_free(self) } +func (self PeerNetwork) free() { C.peernetwork_free(self.inner) } -func (self PeerNetwork) AddPeer(paddr NetAddr) { C.peernetwork_add_peer(self, paddr) } +func (self PeerNetwork) AddPeer(paddr NetAddr) { C.peernetwork_add_peer(self.inner, paddr.inner) } -func (self PeerNetwork) HasPeer(paddr NetAddr) bool { return bool(C.peernetwork_has_peer(self, paddr)) } +func (self PeerNetwork) HasPeer(paddr NetAddr) bool { return bool(C.peernetwork_has_peer(self.inner, paddr.inner)) } -func (self PeerNetwork) GetPeerConn(paddr NetAddr, err *Error) PeerNetworkConn { return C.peernetwork_get_peer_conn(self, paddr, err) } +func (self PeerNetwork) GetPeerConn(paddr NetAddr, err *Error) PeerNetworkConn { + res := &peerNetworkConn{ inner: C.peernetwork_get_peer_conn(self.inner, paddr.inner, err) } + runtime.SetFinalizer(res, func(self PeerNetworkConn) { self.free() }) + return res +} -func (self PeerNetwork) AsMsgNetwork() MsgNetwork { return C.peernetwork_as_msgnetwork(self) } +func (self PeerNetwork) AsMsgNetwork() MsgNetwork { return &msgNetwork{ inner: C.peernetwork_as_msgnetwork(self.inner) } } -func NewMsgNetworkConnFromPeerNetWorkConn(conn PeerNetworkConn) MsgNetworkConn { return C.msgnetwork_conn_new_from_peernetwork_conn(conn) } +func NewMsgNetworkConnFromPeerNetWorkConn(conn PeerNetworkConn) MsgNetworkConn { + res := &msgNetworkConn{ inner: C.msgnetwork_conn_new_from_peernetwork_conn(conn.inner) } + runtime.SetFinalizer(res, func(self MsgNetworkConn) { self.free() }) + return res +} -func (self PeerNetworkConn) Copy() PeerNetworkConn { return C.peernetwork_conn_copy(self) } +func (self PeerNetworkConn) Copy() PeerNetworkConn { + res := &peerNetworkConn { inner: C.peernetwork_conn_copy(self.inner) } + runtime.SetFinalizer(res, func(self PeerNetworkConn) { self.free() }) + return res +} -func (self PeerNetworkConn) Free() { C.peernetwork_conn_free(self) } +func (self PeerNetworkConn) free() { C.peernetwork_conn_free(self.inner) } -func (self PeerNetwork) SendMsgByMove(_moved_msg Msg, paddr NetAddr) { C.peernetwork_send_msg_by_move(self, _moved_msg, paddr) } +func (self PeerNetwork) SendMsgByMove(_moved_msg Msg, paddr NetAddr) { + C.peernetwork_send_msg_by_move(self.inner, _moved_msg.inner, paddr.inner) +} func (self PeerNetwork) MulticastMsgByMove(_moved_msg Msg, paddrs []NetAddr) { na := NewAddrArrayFromAddrs(paddrs) - C.peernetwork_multicast_msg_by_move(self, _moved_msg, na) + C.peernetwork_multicast_msg_by_move(self.inner, _moved_msg.inner, na.inner) } -func (self PeerNetwork) Listen(listenAddr NetAddr, err *Error) { C.peernetwork_listen(self, listenAddr, err) } +func (self PeerNetwork) Listen(listenAddr NetAddr, err *Error) { + C.peernetwork_listen(self.inner, listenAddr.inner, err) +} diff --git a/salticidae b/salticidae index 77a7650..74e4246 160000 --- a/salticidae +++ b/salticidae @@ -1 +1 @@ -Subproject commit 77a765023bff4fa3d41001bdc1de9d106e35f348 +Subproject commit 74e4246565ba5814a92ed9f84b13b17226f219d1 diff --git a/stream.go b/stream.go index d66d085..4fe7d7b 100644 --- a/stream.go +++ b/stream.go @@ -3,95 +3,128 @@ package salticidae // #include // #include "salticidae/stream.h" import "C" +import "runtime" -type ByteArray = *C.struct_bytearray_t +type byteArray struct { + inner *C.struct_bytearray_t +} +type ByteArray = *byteArray + +func NewByteArray() ByteArray { + res := &byteArray{ inner: C.bytearray_new() } + runtime.SetFinalizer(res, func(self ByteArray) { self.free() }) + return res +} -func NewByteArray() ByteArray { return C.bytearray_new() } -func (self ByteArray) Free() { C.bytearray_free(self) } +func (self ByteArray) free() { C.bytearray_free(self.inner) } func NewByteArrayMovedFromDataStream(src DataStream) ByteArray { - return C.bytearray_new_moved_from_datastream(src) + res := &byteArray{ inner: C.bytearray_new_moved_from_datastream(src.inner) } + runtime.SetFinalizer(res, func(self ByteArray) { self.free() }) + return res +} + +type dataStream struct { + inner *C.struct_datastream_t } -type DataStream = *C.struct_datastream_t +type DataStream = *dataStream + +func NewDataStream() DataStream { + res := &dataStream{ inner: C.datastream_new() } + runtime.SetFinalizer(res, func(self DataStream) { self.free() }) + return res +} -func NewDataStream() DataStream { return C.datastream_new() } -func NewDataStreamFromBytes(bytes []byte) DataStream { +func NewDataStreamFromBytes(bytes []byte) (res DataStream) { size := len(bytes) if size > 0 { base := (*C.uint8_t)(&bytes[0]) - return C.datastream_new_from_bytes(base, C.size_t(size)) + res = &dataStream{ inner: C.datastream_new_from_bytes(base, C.size_t(size)) } } else { - return C.datastream_new() + res = &dataStream{ inner: C.datastream_new() } } + runtime.SetFinalizer(res, func(self DataStream) { self.free() }) + return } -func (self DataStream) Free() { C.datastream_free(self) } +func (self DataStream) free() { C.datastream_free(self.inner) } func (self DataStream) AssignByCopy(src DataStream) { - C.datastream_assign_by_copy(self, src) + C.datastream_assign_by_copy(self.inner, src.inner) } func (self DataStream) AssignByMove(src DataStream) { - C.datastream_assign_by_move(self, src) + C.datastream_assign_by_move(self.inner, src.inner) } // TODO: datastream_data -func (self DataStream) Clear() { C.datastream_clear(self) } +func (self DataStream) Clear() { C.datastream_clear(self.inner) } -func (self DataStream) Size() int { return int(C.datastream_size(self)) } +func (self DataStream) Size() int { return int(C.datastream_size(self.inner)) } -func (self DataStream) PutU8(v uint8) bool { return bool(C.datastream_put_u8(self, C.uint8_t(v))) } -func (self DataStream) PutU16(v uint16) bool { return bool(C.datastream_put_u16(self, C.uint16_t(v))) } -func (self DataStream) PutU32(v uint32) bool { return bool(C.datastream_put_u32(self, C.uint32_t(v))) } -func (self DataStream) PutU64(v uint32) bool { return bool(C.datastream_put_u64(self, C.uint64_t(v))) } +func (self DataStream) PutU8(v uint8) bool { return bool(C.datastream_put_u8(self.inner, C.uint8_t(v))) } +func (self DataStream) PutU16(v uint16) bool { return bool(C.datastream_put_u16(self.inner, C.uint16_t(v))) } +func (self DataStream) PutU32(v uint32) bool { return bool(C.datastream_put_u32(self.inner, C.uint32_t(v))) } +func (self DataStream) PutU64(v uint32) bool { return bool(C.datastream_put_u64(self.inner, C.uint64_t(v))) } -func (self DataStream) PutI8(v int8) bool { return bool(C.datastream_put_i8(self, C.int8_t(v))) } -func (self DataStream) PutI16(v int16) bool { return bool(C.datastream_put_i16(self, C.int16_t(v))) } -func (self DataStream) PutI32(v int32) bool { return bool(C.datastream_put_i32(self, C.int32_t(v))) } -func (self DataStream) PutI64(v int32) bool { return bool(C.datastream_put_i64(self, C.int64_t(v))) } +func (self DataStream) PutI8(v int8) bool { return bool(C.datastream_put_i8(self.inner, C.int8_t(v))) } +func (self DataStream) PutI16(v int16) bool { return bool(C.datastream_put_i16(self.inner, C.int16_t(v))) } +func (self DataStream) PutI32(v int32) bool { return bool(C.datastream_put_i32(self.inner, C.int32_t(v))) } +func (self DataStream) PutI64(v int32) bool { return bool(C.datastream_put_i64(self.inner, C.int64_t(v))) } func (self DataStream) PutData(bytes []byte) bool { size := len(bytes) if size > 0 { base := (*C.uint8_t)(&bytes[0]) - return bool(C.datastream_put_data(self, base, C.size_t(size))) + return bool(C.datastream_put_data(self.inner, base, C.size_t(size))) } else { return true } } -func (self DataStream) GetU8(succ *bool) uint8 { return uint8(C.datastream_get_u8(self, (*C.bool)(succ))) } -func (self DataStream) GetU16(succ *bool) uint16 { return uint16(C.datastream_get_u16(self, (*C.bool)(succ))) } -func (self DataStream) GetU32(succ *bool) uint32 { return uint32(C.datastream_get_u32(self, (*C.bool)(succ))) } -func (self DataStream) GetU64(succ *bool) uint64 { return uint64(C.datastream_get_u64(self, (*C.bool)(succ))) } +func (self DataStream) GetU8(succ *bool) uint8 { return uint8(C.datastream_get_u8(self.inner, (*C.bool)(succ))) } +func (self DataStream) GetU16(succ *bool) uint16 { return uint16(C.datastream_get_u16(self.inner, (*C.bool)(succ))) } +func (self DataStream) GetU32(succ *bool) uint32 { return uint32(C.datastream_get_u32(self.inner, (*C.bool)(succ))) } +func (self DataStream) GetU64(succ *bool) uint64 { return uint64(C.datastream_get_u64(self.inner, (*C.bool)(succ))) } -func (self DataStream) GetI8(succ *bool) int8 { return int8(C.datastream_get_i8(self, (*C.bool)(succ))) } -func (self DataStream) GetI16(succ *bool) int16 { return int16(C.datastream_get_i16(self, (*C.bool)(succ))) } -func (self DataStream) GetI32(succ *bool) int32 { return int32(C.datastream_get_i32(self, (*C.bool)(succ))) } -func (self DataStream) GetI64(succ *bool) int64 { return int64(C.datastream_get_i64(self, (*C.bool)(succ))) } +func (self DataStream) GetI8(succ *bool) int8 { return int8(C.datastream_get_i8(self.inner, (*C.bool)(succ))) } +func (self DataStream) GetI16(succ *bool) int16 { return int16(C.datastream_get_i16(self.inner, (*C.bool)(succ))) } +func (self DataStream) GetI32(succ *bool) int32 { return int32(C.datastream_get_i32(self.inner, (*C.bool)(succ))) } +func (self DataStream) GetI64(succ *bool) int64 { return int64(C.datastream_get_i64(self.inner, (*C.bool)(succ))) } func (self DataStream) GetDataInPlace(length int) []byte { - base := C.datastream_get_data_inplace(self, C.size_t(length)) + base := C.datastream_get_data_inplace(self.inner, C.size_t(length)) return C.GoBytes(rawptr_t(base), C.int(length)) } -type UInt256 = *C.uint256_t +type uint256 struct { + inner *C.uint256_t +} + +type UInt256 = *uint256 -func NewUInt256() UInt256 { return C.uint256_new() } -func (self UInt256) Free() { C.uint256_free(self) } -func (self UInt256) UInt256IsNull() bool { return bool(C.uint256_is_null(self)) } -func (self UInt256) UInt256IsEq(other UInt256) bool { return bool(C.uint256_is_eq(self, other)) } -func (self UInt256) Serialize(s DataStream) { C.uint256_serialize(self, s) } -func (self UInt256) Unserialize(s DataStream) { C.uint256_unserialize(self, s) } -func (self UInt256) IsEq(other UInt256) bool { return bool(C.uint256_is_eq(self, other)) } +func NewUInt256() UInt256 { + res := &uint256{ inner: C.uint256_new() } + runtime.SetFinalizer(res, func(self UInt256) { self.free() }) + return res +} + +func (self UInt256) free() { C.uint256_free(self.inner) } +func (self UInt256) UInt256IsNull() bool { return bool(C.uint256_is_null(self.inner)) } +func (self UInt256) UInt256IsEq(other UInt256) bool { return bool(C.uint256_is_eq(self.inner, other.inner)) } +func (self UInt256) Serialize(s DataStream) { C.uint256_serialize(self.inner, s.inner) } +func (self UInt256) Unserialize(s DataStream) { C.uint256_unserialize(self.inner, s.inner) } +func (self UInt256) IsEq(other UInt256) bool { return bool(C.uint256_is_eq(self.inner, other.inner)) } func (self DataStream) GetHash() UInt256 { - return C.datastream_get_hash(self) + res := &uint256{ inner: C.datastream_get_hash(self.inner) } + runtime.SetFinalizer(res, func(self UInt256) { self.free() }) + return res } func (self DataStream) GetHex() string { - tmp := C.datastream_get_hex(self) + tmp := C.datastream_get_hex(self.inner) res := C.GoString(tmp) C.free(rawptr_t(tmp)) return res @@ -101,6 +134,5 @@ func (self UInt256) GetHex() string { s := NewDataStream() self.Serialize(s) res := s.GetHex() - s.Free() return res } diff --git a/test_msgnet/main.go b/test_msgnet/main.go index 4c885d3..fd561f7 100644 --- a/test_msgnet/main.go +++ b/test_msgnet/main.go @@ -29,9 +29,9 @@ func msgHelloSerialize(name string, text string) salticidae.Msg { serialized.PutData(t) serialized.PutData([]byte(name)) serialized.PutData([]byte(text)) + s := salticidae.NewByteArrayMovedFromDataStream(serialized) return salticidae.NewMsgMovedFromByteArray( - MSG_OPCODE_HELLO, - salticidae.NewByteArrayMovedFromDataStream(serialized)) + MSG_OPCODE_HELLO, s) } func msgHelloUnserialize(msg salticidae.Msg) (name string, text string) { @@ -39,12 +39,12 @@ func msgHelloUnserialize(msg salticidae.Msg) (name string, text string) { length := binary.LittleEndian.Uint32(p.GetDataInPlace(4)) name = string(p.GetDataInPlace(int(length))) text = string(p.GetDataInPlace(p.Size())) - p.Free() return } func msgAckSerialize() salticidae.Msg { - return salticidae.NewMsgMovedFromByteArray(MSG_OPCODE_ACK, salticidae.NewByteArray()) + s := salticidae.NewByteArray() + return salticidae.NewMsgMovedFromByteArray(MSG_OPCODE_ACK, s) } func checkError(err *salticidae.Error) { @@ -71,8 +71,8 @@ func onTerm(_ C.int, _ unsafe.Pointer) { //export onReceiveHello func onReceiveHello(_msg *C.struct_msg_t, _conn *C.struct_msgnetwork_conn_t, _ unsafe.Pointer) { - msg := salticidae.Msg(_msg) - conn := salticidae.MsgNetworkConn(_conn) + msg := salticidae.MsgFromC(salticidae.CMsg(_msg)) + conn := salticidae.MsgNetworkConnFromC(salticidae.CMsgNetworkConn(_conn)) net := conn.GetNet() myName := bob.name if net == alice.net { @@ -86,7 +86,7 @@ func onReceiveHello(_msg *C.struct_msg_t, _conn *C.struct_msgnetwork_conn_t, _ u //export onReceiveAck func onReceiveAck(_ *C.struct_msg_t, _conn *C.struct_msgnetwork_conn_t, _ unsafe.Pointer) { - conn := salticidae.MsgNetworkConn(_conn) + conn := salticidae.MsgNetworkConnFromC(salticidae.CMsgNetworkConn(_conn)) net := conn.GetNet() name := bob.name if net == alice.net { @@ -97,18 +97,18 @@ func onReceiveAck(_ *C.struct_msg_t, _conn *C.struct_msgnetwork_conn_t, _ unsafe //export connHandler func connHandler(_conn *C.struct_msgnetwork_conn_t, connected C.bool, _ unsafe.Pointer) { - conn := salticidae.MsgNetworkConn(_conn) + conn := salticidae.MsgNetworkConnFromC(salticidae.CMsgNetworkConn(_conn)) net := conn.GetNet() - n := &bob + n := bob if net == alice.net { - n = &alice + n = alice } name := n.name if connected { if conn.GetMode() == salticidae.CONN_MODE_ACTIVE { - fmt.Printf("[%s] Connected, sending hello.", name) + fmt.Printf("[%s] Connected, sending hello.\n", name) hello := msgHelloSerialize(name, "Hello there!") - n.net.SendMsgByMove(hello, conn) + (*n.net).SendMsgByMove(hello, conn) } else { fmt.Printf("[%s] Accepted, waiting for greetings.\n", name) } @@ -116,8 +116,7 @@ func connHandler(_conn *C.struct_msgnetwork_conn_t, connected C.bool, _ unsafe.P fmt.Printf("[%s] Disconnected, retrying.\n", name) addr := conn.GetAddr() err := salticidae.NewError() - net.Connect(addr, &err).Free() - addr.Free() + net.Connect(addr, &err) } } @@ -139,7 +138,6 @@ func genMyNet(ec salticidae.EventContext, name string) MyNet { n.net.RegHandler(MSG_OPCODE_ACK, salticidae.MsgNetworkMsgCallback(C.onReceiveAck), nil) n.net.RegConnHandler(salticidae.MsgNetworkConnCallback(C.connHandler), nil) n.net.RegErrorHandler(salticidae.MsgNetworkErrorCallback(C.errorHandler), nil) - netconfig.Free() return n } @@ -161,24 +159,15 @@ func main() { bob.net.Listen(bob_addr, &err) checkError(&err) - alice.net.Connect(bob_addr, &err).Free() + alice.net.Connect(bob_addr, &err) checkError(&err) - bob.net.Connect(alice_addr, &err).Free() + bob.net.Connect(alice_addr, &err) checkError(&err) - alice_addr.Free() - bob_addr.Free() - ev_int := salticidae.NewSigEvent(ec, salticidae.SigEventCallback(C.onTerm), nil) ev_int.Add(salticidae.SIGINT) ev_term := salticidae.NewSigEvent(ec, salticidae.SigEventCallback(C.onTerm), nil) ev_term.Add(salticidae.SIGTERM) ec.Dispatch() - - alice.net.Free() - bob.net.Free() - ev_int.Free() - ev_term.Free() - ec.Free() } diff --git a/test_p2p_stress/main.go b/test_p2p_stress/main.go index 7cda52d..404956f 100644 --- a/test_p2p_stress/main.go +++ b/test_p2p_stress/main.go @@ -1,6 +1,7 @@ package main // #cgo CFLAGS: -I${SRCDIR}/../salticidae/include/ +// #cgo LDFLAGS: ${SRCDIR}/../salticidae/libsalticidae.so -Wl,-rpath=${SRCDIR}/salticidae/ // #include // #include // #include "salticidae/network.h" @@ -68,7 +69,6 @@ func msgAckUnserialize(msg salticidae.Msg) salticidae.UInt256 { p := msg.ConsumePayload() hash := salticidae.NewUInt256() hash.Unserialize(p) - p.Free() return hash } @@ -89,11 +89,13 @@ type TestContext struct { func (self TestContext) Free() { if self.timer != nil { - self.timer.Free() C.free(unsafe.Pointer(self.timer_ctx)) } - if self.hash != nil { - self.hash.Free() +} + +func (self AppContext) Free() { + for _, tc:= range self.tc { + tc.Free() } } @@ -105,16 +107,6 @@ type AppContext struct { tc map[uint64] *TestContext } -func (self AppContext) Free() { - self.addr.Free() - self.net.Free() - self.tcall.Free() - for _, tc:= range self.tc { - tc.Free() - } - self.ec.Free() -} - func NewTestContext() TestContext { return TestContext { ncompleted: 0 } } @@ -137,10 +129,6 @@ func sendRand(size int, app *AppContext, conn salticidae.MsgNetworkConn) { msg, hash := msgRandSerialize(size) addr := conn.GetAddr() tc := app.getTC(addr2id(addr)) - addr.Free() - if tc.hash != nil { - salticidae.UInt256(tc.hash).Free() - } tc.hash = hash app.net.AsMsgNetwork().SendMsgByMove(msg, conn) } @@ -149,6 +137,7 @@ var apps []AppContext var threads sync.WaitGroup var segBuffSize = 4096 var ec salticidae.EventContext +var ids []*C.int //export onTimeout func onTimeout(_ *C.timerev_t, userdata unsafe.Pointer) { @@ -156,7 +145,9 @@ func onTimeout(_ *C.timerev_t, userdata unsafe.Pointer) { app := &apps[ctx.app_id] tc := app.getTC(uint64(ctx.addr_id)) tc.ncompleted++ - app.net.AsMsgNetwork().Terminate(salticidae.MsgNetworkConn(ctx.conn)) + app.net.AsMsgNetwork().Terminate( + salticidae.MsgNetworkConnFromC( + salticidae.CMsgNetworkConn(ctx.conn))) var s string for addr_id, v := range app.tc { s += fmt.Sprintf(" %d(%d)", C.ntohs(C.ushort(addr_id >> 32)), v.ncompleted) @@ -166,33 +157,29 @@ func onTimeout(_ *C.timerev_t, userdata unsafe.Pointer) { //export onReceiveRand func onReceiveRand(_msg *C.struct_msg_t, _conn *C.struct_msgnetwork_conn_t, userdata unsafe.Pointer) { - msg := salticidae.Msg(_msg) + msg := salticidae.MsgFromC(salticidae.CMsg(_msg)) bytes := msgRandUnserialize(msg) hash := bytes.GetHash() - bytes.Free() - conn := salticidae.MsgNetworkConn(_conn) + conn := salticidae.MsgNetworkConnFromC(salticidae.CMsgNetworkConn(_conn)) net := conn.GetNet() ack := msgAckSerialize(hash) - hash.Free() net.SendMsgByMove(ack, conn) } //export onReceiveAck func onReceiveAck(_msg *C.struct_msg_t, _conn *C.struct_msgnetwork_conn_t, userdata unsafe.Pointer) { - hash := msgAckUnserialize(salticidae.Msg(_msg)) + hash := msgAckUnserialize(salticidae.MsgFromC(salticidae.CMsg(_msg))) id := *(* int)(userdata) app := &apps[id] - conn := salticidae.MsgNetworkConn(_conn) + conn := salticidae.MsgNetworkConnFromC(salticidae.CMsgNetworkConn(_conn)) _addr := conn.GetAddr() addr := addr2id(_addr) - _addr.Free() tc := app.getTC(addr) if !hash.IsEq(tc.hash) { //fmt.Printf("%s %s\n", hash.GetHex(), tc.hash.GetHex()) panic("corrupted I/O!") } - hash.Free() if tc.state == segBuffSize * 2 { sendRand(tc.state, app, conn) @@ -200,10 +187,9 @@ func onReceiveAck(_msg *C.struct_msg_t, _conn *C.struct_msgnetwork_conn_t, userd ctx := C.timeout_callback_context_new() ctx.app_id = C.int(id) ctx.addr_id = C.uint64_t(addr) - ctx.conn = (*C.struct_msgnetwork_conn_t)(conn.Copy()) + ctx.conn = C.msgnetwork_conn_copy(_conn) if tc.timer != nil { - tc.timer.Free() - salticidae.MsgNetworkConn(tc.timer_ctx.conn).Free() + C.msgnetwork_conn_free(tc.timer_ctx.conn) C.free(unsafe.Pointer(tc.timer_ctx)) } tc.timer = salticidae.NewTimerEvent(app.ec, salticidae.TimerEventCallback(C.onTimeout), unsafe.Pointer(ctx)) @@ -221,14 +207,13 @@ func onReceiveAck(_msg *C.struct_msg_t, _conn *C.struct_msgnetwork_conn_t, userd //export connHandler func connHandler(_conn *C.struct_msgnetwork_conn_t, connected C.bool, userdata unsafe.Pointer) { - conn := salticidae.MsgNetworkConn(_conn) + conn := salticidae.MsgNetworkConnFromC(salticidae.CMsgNetworkConn(_conn)) id := *(*int)(userdata) app := &apps[id] if connected { if conn.GetMode() == salticidae.CONN_MODE_ACTIVE { addr := conn.GetAddr() tc := app.getTC(addr2id(addr)) - addr.Free() tc.state = 1 fmt.Printf("INFO: increasing phase\n") sendRand(tc.state, app, conn) @@ -246,7 +231,7 @@ func errorHandler(_err *C.struct_SalticidaeCError, fatal C.bool, _ unsafe.Pointe //export onStopLoop func onStopLoop(_ *C.threadcall_handle_t, userdata unsafe.Pointer) { - ec := salticidae.EventContext(userdata) + ec := apps[*(*int)(userdata)].ec ec.Stop() } @@ -256,7 +241,7 @@ func onTerm(_ C.int, _ unsafe.Pointer) { a := &apps[i] a.tcall.AsyncCall( salticidae.ThreadCallCallback(C.onStopLoop), - unsafe.Pointer(a.ec)) + unsafe.Pointer(ids[i])) } threads.Wait() ec.Stop() @@ -277,7 +262,7 @@ func main() { netconfig.ConnTimeout(5) netconfig.PingPeriod(2) apps = make([]AppContext, len(addrs)) - ids := make([](*C.int), len(addrs)) + ids = make([](*C.int), len(addrs)) for i, addr := range addrs { ec := salticidae.NewEventContext() apps[i] = AppContext { @@ -297,7 +282,6 @@ func main() { net.RegErrorHandler(salticidae.MsgNetworkErrorCallback(C.errorHandler), _i) net.Start() } - netconfig.Free() threads.Add(len(apps)) for i, _ := range apps { @@ -324,8 +308,4 @@ func main() { ev_term.Add(salticidae.SIGTERM) ec.Dispatch() - - ev_int.Free() - ev_term.Free() - ec.Free() } -- cgit v1.2.3