Skip to content

Commit a534c20

Browse files
committed
Merge pull request #217 from geky/socket_event_coalescing
Add socket event coalescing to reduce cpu usage in lazy implementations
2 parents 653832e + f567252 commit a534c20

File tree

8 files changed

+89
-53
lines changed

8 files changed

+89
-53
lines changed

net/NetworkSocketAPI/Socket.cpp

Lines changed: 3 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,6 @@ Socket::Socket()
2323
{
2424
}
2525

26-
Socket::~Socket()
27-
{
28-
// Underlying close is thread safe
29-
close();
30-
}
31-
3226
int Socket::open(NetworkStack *iface, nsapi_protocol_t proto)
3327
{
3428
_lock.lock();
@@ -47,7 +41,8 @@ int Socket::open(NetworkStack *iface, nsapi_protocol_t proto)
4741
}
4842

4943
_socket = socket;
50-
_iface->socket_attach(_socket, &Socket::thunk, this);
44+
_event.attach(this, &Socket::event);
45+
_iface->socket_attach(_socket, Callback<void()>::thunk, &_event);
5146

5247
_lock.unlock();
5348

@@ -69,7 +64,7 @@ int Socket::close()
6964

7065
// Wakeup anything in a blocking operation
7166
// on this socket
72-
socket_event();
67+
event();
7368

7469
_lock.unlock();
7570
return ret;
@@ -156,16 +151,3 @@ void Socket::attach(Callback<void()> callback)
156151

157152
_lock.unlock();
158153
}
159-
160-
void Socket::thunk(void *data)
161-
{
162-
Socket *self = (Socket *)data;
163-
self->socket_event();
164-
}
165-
166-
void Socket::socket_event(void)
167-
{
168-
if (_callback) {
169-
_callback();
170-
}
171-
}

net/NetworkSocketAPI/Socket.h

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ class Socket {
2929
*
3030
* Closes socket if the socket is still open
3131
*/
32-
virtual ~Socket();
32+
virtual ~Socket() {}
3333

3434
/** Opens a socket
3535
*
@@ -169,13 +169,12 @@ class Socket {
169169
protected:
170170
Socket();
171171
int open(NetworkStack *iface, nsapi_protocol_t proto);
172-
173-
static void thunk(void *);
174-
virtual void socket_event(void);
172+
virtual void event() = 0;
175173

176174
NetworkStack *_iface;
177175
void *_socket;
178176
uint32_t _timeout;
177+
Callback<void()> _event;
179178
Callback<void()> _callback;
180179
rtos::Mutex _lock;
181180
};

net/NetworkSocketAPI/TCPServer.cpp

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,22 @@
1717
#include "TCPServer.h"
1818
#include "Timer.h"
1919

20-
TCPServer::TCPServer(): _accept_sem(0)
20+
TCPServer::TCPServer()
21+
: _pending(0), _accept_sem(0)
2122
{
2223
}
2324

24-
TCPServer::TCPServer(NetworkStack *iface): _accept_sem(0)
25+
TCPServer::TCPServer(NetworkStack *iface)
26+
: _pending(0), _accept_sem(0)
2527
{
2628
open(iface);
2729
}
2830

31+
TCPServer::~TCPServer()
32+
{
33+
close();
34+
}
35+
2936
int TCPServer::open(NetworkStack *iface)
3037
{
3138
return Socket::open(iface, NSAPI_TCP);
@@ -55,6 +62,7 @@ int TCPServer::accept(TCPSocket *connection)
5562
break;
5663
}
5764

65+
_pending = 0;
5866
void *socket;
5967
ret = _iface->socket_accept(&socket, _socket);
6068
if (0 == ret) {
@@ -66,7 +74,8 @@ int TCPServer::accept(TCPSocket *connection)
6674

6775
connection->_iface = _iface;
6876
connection->_socket = socket;
69-
_iface->socket_attach(socket, &Socket::thunk, connection);
77+
connection->_event = Callback<void()>(connection, &TCPSocket::event);
78+
_iface->socket_attach(socket, &Callback<void()>::thunk, &connection->_event);
7079

7180
connection->_lock.unlock();
7281
break;
@@ -90,12 +99,15 @@ int TCPServer::accept(TCPSocket *connection)
9099
return ret;
91100
}
92101

93-
void TCPServer::socket_event()
102+
void TCPServer::event()
94103
{
95-
int32_t status = _accept_sem.wait(0);
96-
if (status <= 1) {
104+
int32_t acount = _accept_sem.wait(0);
105+
if (acount <= 1) {
97106
_accept_sem.release();
98107
}
99108

100-
Socket::socket_event();
109+
_pending += 1;
110+
if (_callback && _pending == 1) {
111+
_callback();
112+
}
101113
}

net/NetworkSocketAPI/TCPServer.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,12 @@ class TCPServer : public Socket {
3232
*/
3333
TCPServer();
3434

35+
/** Destroy a socket
36+
*
37+
* Closes socket if the socket is still open
38+
*/
39+
virtual ~TCPServer();
40+
3541
/** Create a socket on a network stack
3642
*
3743
* Creates and opens a socket on the specified network stack.
@@ -76,7 +82,8 @@ class TCPServer : public Socket {
7682
*/
7783
int accept(TCPSocket *connection);
7884
protected:
79-
virtual void socket_event(void);
85+
virtual void event();
86+
volatile unsigned _pending;
8087
rtos::Semaphore _accept_sem;
8188
};
8289

net/NetworkSocketAPI/TCPSocket.cpp

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,16 +17,23 @@
1717
#include "TCPSocket.h"
1818
#include "Timer.h"
1919

20-
TCPSocket::TCPSocket(): _read_sem(0), _write_sem(0)
20+
TCPSocket::TCPSocket()
21+
: _pending(0), _read_sem(0), _write_sem(0)
2122
{
2223
}
2324

24-
TCPSocket::TCPSocket(NetworkStack *iface): _read_sem(0), _write_sem(0)
25+
TCPSocket::TCPSocket(NetworkStack *iface)
26+
: _pending(0), _read_sem(0), _write_sem(0)
2527
{
2628
// TCPSocket::open is thread safe
2729
open(iface);
2830
}
2931

32+
TCPSocket::~TCPSocket()
33+
{
34+
close();
35+
}
36+
3037
int TCPSocket::open(NetworkStack *iface)
3138
{
3239
// Socket::open is thread safe
@@ -74,6 +81,7 @@ int TCPSocket::send(const void *data, unsigned size)
7481
break;
7582
}
7683

84+
_pending = 0;
7785
int sent = _iface->socket_send(_socket, data, size);
7886
if ((0 == _timeout) || (NSAPI_ERROR_WOULD_BLOCK != sent)) {
7987
ret = sent;
@@ -114,6 +122,7 @@ int TCPSocket::recv(void *data, unsigned size)
114122
break;
115123
}
116124

125+
_pending = 0;
117126
int recv = _iface->socket_recv(_socket, data, size);
118127
if ((0 == _timeout) || (NSAPI_ERROR_WOULD_BLOCK != recv)) {
119128
ret = recv;
@@ -140,17 +149,19 @@ int TCPSocket::recv(void *data, unsigned size)
140149
return ret;
141150
}
142151

143-
void TCPSocket::socket_event()
152+
void TCPSocket::event()
144153
{
145-
int32_t count;
146-
count = _write_sem.wait(0);
147-
if (count <= 1) {
154+
int32_t wcount = _write_sem.wait(0);
155+
if (wcount <= 1) {
148156
_write_sem.release();
149157
}
150-
count = _read_sem.wait(0);
151-
if (count <= 1) {
158+
int32_t rcount = _read_sem.wait(0);
159+
if (rcount <= 1) {
152160
_read_sem.release();
153161
}
154162

155-
Socket::socket_event();
163+
_pending += 1;
164+
if (_callback && _pending == 1) {
165+
_callback();
166+
}
156167
}

net/NetworkSocketAPI/TCPSocket.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,12 @@ class TCPSocket : public Socket {
3131
*/
3232
TCPSocket();
3333

34+
/** Destroy a socket
35+
*
36+
* Closes socket if the socket is still open
37+
*/
38+
virtual ~TCPSocket();
39+
3440
/** Create a socket on a network stack
3541
*
3642
* Creates and opens a socket on the specified network stack.
@@ -103,7 +109,8 @@ class TCPSocket : public Socket {
103109
int recv(void *data, unsigned size);
104110

105111
protected:
106-
virtual void socket_event(void);
112+
virtual void event();
113+
volatile unsigned _pending;
107114
rtos::Mutex _read_lock;
108115
rtos::Semaphore _read_sem;
109116
rtos::Mutex _write_lock;

net/NetworkSocketAPI/UDPSocket.cpp

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,22 @@
1717
#include "UDPSocket.h"
1818
#include "Timer.h"
1919

20-
UDPSocket::UDPSocket(): _read_sem(0), _write_sem(0)
20+
UDPSocket::UDPSocket()
21+
: _pending(0), _read_sem(0), _write_sem(0)
2122
{
2223
}
2324

24-
UDPSocket::UDPSocket(NetworkStack *iface): _read_sem(0), _write_sem(0)
25+
UDPSocket::UDPSocket(NetworkStack *iface)
26+
: _pending(0), _read_sem(0), _write_sem(0)
2527
{
2628
open(iface);
2729
}
2830

31+
UDPSocket::~UDPSocket()
32+
{
33+
close();
34+
}
35+
2936
int UDPSocket::open(NetworkStack *iface)
3037
{
3138
return Socket::open(iface, NSAPI_UDP);
@@ -58,6 +65,7 @@ int UDPSocket::sendto(const SocketAddress &address, const void *data, unsigned s
5865
break;
5966
}
6067

68+
_pending = 0;
6169
int sent = _iface->socket_sendto(_socket, address, data, size);
6270
if ((0 == _timeout) || (NSAPI_ERROR_WOULD_BLOCK != sent)) {
6371
ret = sent;
@@ -98,6 +106,7 @@ int UDPSocket::recvfrom(SocketAddress *address, void *buffer, unsigned size)
98106
break;
99107
}
100108

109+
_pending = 0;
101110
int recv = _iface->socket_recvfrom(_socket, address, buffer, size);
102111
if ((0 == _timeout) || (NSAPI_ERROR_WOULD_BLOCK != recv)) {
103112
ret = recv;
@@ -124,17 +133,19 @@ int UDPSocket::recvfrom(SocketAddress *address, void *buffer, unsigned size)
124133
return ret;
125134
}
126135

127-
void UDPSocket::socket_event()
136+
void UDPSocket::event()
128137
{
129-
int32_t count;
130-
count = _write_sem.wait(0);
131-
if (count <= 1) {
138+
int32_t wcount = _write_sem.wait(0);
139+
if (wcount <= 1) {
132140
_write_sem.release();
133141
}
134-
count = _read_sem.wait(0);
135-
if (count <= 1) {
142+
int32_t rcount = _read_sem.wait(0);
143+
if (rcount <= 1) {
136144
_read_sem.release();
137145
}
138146

139-
Socket::socket_event();
147+
_pending += 1;
148+
if (_callback && _pending == 1) {
149+
_callback();
150+
}
140151
}

net/NetworkSocketAPI/UDPSocket.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,12 @@ class UDPSocket : public Socket {
3131
*/
3232
UDPSocket();
3333

34+
/** Destroy a socket
35+
*
36+
* Closes socket if the socket is still open
37+
*/
38+
virtual ~UDPSocket();
39+
3440
/** Create a socket on a network stack
3541
*
3642
* Creates and opens a socket on the specified network stack.
@@ -102,7 +108,8 @@ class UDPSocket : public Socket {
102108
*/
103109
int recvfrom(SocketAddress *address, void *data, unsigned size);
104110
protected:
105-
virtual void socket_event(void);
111+
virtual void event();
112+
volatile unsigned _pending;
106113
rtos::Mutex _read_lock;
107114
rtos::Semaphore _read_sem;
108115
rtos::Mutex _write_lock;

0 commit comments

Comments
 (0)