Skip to content

Commit dd169bf

Browse files
committed
add example for tcp echo server
1 parent c62c650 commit dd169bf

File tree

9 files changed

+2012
-13
lines changed

9 files changed

+2012
-13
lines changed

Makefile

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,27 @@
11
CC = gcc
2-
INCLUDE =
2+
INCLUDE = -I${JUMBO_ROOT}/include
33
BIN =
4-
LIB =
4+
LIB = -L${JUMBO_ROOT}/lib -lhiredis
55

66
#CFLAGS = -D_GNU_SOURCE -Wall -g
7-
CFLAGS = -D_GNU_SOURCE -Wall -O2
7+
CFLAGS = -Wall -O2
88
LDFLAGS =
99

1010
TARGET = ae-main
1111

1212
all: $(TARGET)
1313

14-
ae-main: ae_main.o ae.o
14+
ae-main: ae_main.o ae.o anet.o
15+
$(CC) -o $@ $^ $(LIB)
16+
17+
benchmark: benchmark.o ae.o anet.o sds.o adlist.o
1518
$(CC) -o $@ $^ $(LIB)
1619

1720
%.o : %.c
1821
$(CC) -c $(CFLAGS) $< $(INCLUDE)
1922

2023
clean :
21-
$(RM) $(TARGET) *.o
24+
$(RM) $(TARGET) benchmark *.o
2225

2326

2427

adlist.c

Lines changed: 360 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,360 @@
1+
/* adlist.c - A generic doubly linked list implementation
2+
*
3+
* Copyright (c) 2006-2010, Salvatore Sanfilippo <antirez at gmail dot com>
4+
* All rights reserved.
5+
*
6+
* Redistribution and use in source and binary forms, with or without
7+
* modification, are permitted provided that the following conditions are met:
8+
*
9+
* * Redistributions of source code must retain the above copyright notice,
10+
* this list of conditions and the following disclaimer.
11+
* * Redistributions in binary form must reproduce the above copyright
12+
* notice, this list of conditions and the following disclaimer in the
13+
* documentation and/or other materials provided with the distribution.
14+
* * Neither the name of Redis nor the names of its contributors may be used
15+
* to endorse or promote products derived from this software without
16+
* specific prior written permission.
17+
*
18+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19+
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20+
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21+
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
22+
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23+
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24+
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25+
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26+
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27+
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28+
* POSSIBILITY OF SUCH DAMAGE.
29+
*/
30+
31+
32+
#include "fmacros.h"
33+
34+
#include <stdlib.h>
35+
#include "adlist.h"
36+
37+
/* Create a new list. The created list can be freed with
38+
* AlFreeList(), but private value of every node need to be freed
39+
* by the user before to call AlFreeList().
40+
*
41+
* On error, NULL is returned. Otherwise the pointer to the new list. */
42+
list *listCreate(void)
43+
{
44+
struct list *list;
45+
46+
if ((list = malloc(sizeof(*list))) == NULL)
47+
return NULL;
48+
list->head = list->tail = NULL;
49+
list->len = 0;
50+
list->dup = NULL;
51+
list->free = NULL;
52+
list->match = NULL;
53+
return list;
54+
}
55+
56+
/* Free the whole list.
57+
*
58+
* This function can't fail. */
59+
void listRelease(list *list)
60+
{
61+
unsigned long len;
62+
listNode *current, *next;
63+
64+
current = list->head;
65+
len = list->len;
66+
while(len--) {
67+
next = current->next;
68+
if (list->free) list->free(current->value);
69+
free(current);
70+
current = next;
71+
}
72+
free(list);
73+
}
74+
75+
/* Add a new node to the list, to head, contaning the specified 'value'
76+
* pointer as value.
77+
*
78+
* On error, NULL is returned and no operation is performed (i.e. the
79+
* list remains unaltered).
80+
* On success the 'list' pointer you pass to the function is returned. */
81+
list *listAddNodeHead(list *list, void *value)
82+
{
83+
listNode *node;
84+
85+
if ((node = malloc(sizeof(*node))) == NULL)
86+
return NULL;
87+
node->value = value;
88+
if (list->len == 0) {
89+
list->head = list->tail = node;
90+
node->prev = node->next = NULL;
91+
} else {
92+
node->prev = NULL;
93+
node->next = list->head;
94+
list->head->prev = node;
95+
list->head = node;
96+
}
97+
list->len++;
98+
return list;
99+
}
100+
101+
/* Add a new node to the list, to tail, containing the specified 'value'
102+
* pointer as value.
103+
*
104+
* On error, NULL is returned and no operation is performed (i.e. the
105+
* list remains unaltered).
106+
* On success the 'list' pointer you pass to the function is returned. */
107+
list *listAddNodeTail(list *list, void *value)
108+
{
109+
listNode *node;
110+
111+
if ((node = malloc(sizeof(*node))) == NULL)
112+
return NULL;
113+
node->value = value;
114+
if (list->len == 0) {
115+
list->head = list->tail = node;
116+
node->prev = node->next = NULL;
117+
} else {
118+
node->prev = list->tail;
119+
node->next = NULL;
120+
list->tail->next = node;
121+
list->tail = node;
122+
}
123+
list->len++;
124+
return list;
125+
}
126+
127+
list *listInsertNode(list *list, listNode *old_node, void *value, int after) {
128+
listNode *node;
129+
130+
if ((node = malloc(sizeof(*node))) == NULL)
131+
return NULL;
132+
node->value = value;
133+
if (after) {
134+
node->prev = old_node;
135+
node->next = old_node->next;
136+
if (list->tail == old_node) {
137+
list->tail = node;
138+
}
139+
} else {
140+
node->next = old_node;
141+
node->prev = old_node->prev;
142+
if (list->head == old_node) {
143+
list->head = node;
144+
}
145+
}
146+
if (node->prev != NULL) {
147+
node->prev->next = node;
148+
}
149+
if (node->next != NULL) {
150+
node->next->prev = node;
151+
}
152+
list->len++;
153+
return list;
154+
}
155+
156+
/* Remove the specified node from the specified list.
157+
* It's up to the caller to free the private value of the node.
158+
*
159+
* This function can't fail. */
160+
void listDelNode(list *list, listNode *node)
161+
{
162+
if (node->prev)
163+
node->prev->next = node->next;
164+
else
165+
list->head = node->next;
166+
if (node->next)
167+
node->next->prev = node->prev;
168+
else
169+
list->tail = node->prev;
170+
if (list->free) list->free(node->value);
171+
free(node);
172+
list->len--;
173+
}
174+
175+
/* Returns a list iterator 'iter'. After the initialization every
176+
* call to listNext() will return the next element of the list.
177+
*
178+
* This function can't fail. */
179+
listIter *listGetIterator(list *list, int direction)
180+
{
181+
listIter *iter;
182+
183+
if ((iter = malloc(sizeof(*iter))) == NULL) return NULL;
184+
if (direction == AL_START_HEAD)
185+
iter->next = list->head;
186+
else
187+
iter->next = list->tail;
188+
iter->direction = direction;
189+
return iter;
190+
}
191+
192+
/* Release the iterator memory */
193+
void listReleaseIterator(listIter *iter) {
194+
free(iter);
195+
}
196+
197+
/* Create an iterator in the list private iterator structure */
198+
void listRewind(list *list, listIter *li) {
199+
li->next = list->head;
200+
li->direction = AL_START_HEAD;
201+
}
202+
203+
void listRewindTail(list *list, listIter *li) {
204+
li->next = list->tail;
205+
li->direction = AL_START_TAIL;
206+
}
207+
208+
/* Return the next element of an iterator.
209+
* It's valid to remove the currently returned element using
210+
* listDelNode(), but not to remove other elements.
211+
*
212+
* The function returns a pointer to the next element of the list,
213+
* or NULL if there are no more elements, so the classical usage patter
214+
* is:
215+
*
216+
* iter = listGetIterator(list,<direction>);
217+
* while ((node = listNext(iter)) != NULL) {
218+
* doSomethingWith(listNodeValue(node));
219+
* }
220+
*
221+
* */
222+
listNode *listNext(listIter *iter)
223+
{
224+
listNode *current = iter->next;
225+
226+
if (current != NULL) {
227+
if (iter->direction == AL_START_HEAD)
228+
iter->next = current->next;
229+
else
230+
iter->next = current->prev;
231+
}
232+
return current;
233+
}
234+
235+
/* Duplicate the whole list. On out of memory NULL is returned.
236+
* On success a copy of the original list is returned.
237+
*
238+
* The 'Dup' method set with listSetDupMethod() function is used
239+
* to copy the node value. Otherwise the same pointer value of
240+
* the original node is used as value of the copied node.
241+
*
242+
* The original list both on success or error is never modified. */
243+
list *listDup(list *orig)
244+
{
245+
list *copy;
246+
listIter *iter;
247+
listNode *node;
248+
249+
if ((copy = listCreate()) == NULL)
250+
return NULL;
251+
copy->dup = orig->dup;
252+
copy->free = orig->free;
253+
copy->match = orig->match;
254+
iter = listGetIterator(orig, AL_START_HEAD);
255+
while((node = listNext(iter)) != NULL) {
256+
void *value;
257+
258+
if (copy->dup) {
259+
value = copy->dup(node->value);
260+
if (value == NULL) {
261+
listRelease(copy);
262+
listReleaseIterator(iter);
263+
return NULL;
264+
}
265+
} else
266+
value = node->value;
267+
if (listAddNodeTail(copy, value) == NULL) {
268+
listRelease(copy);
269+
listReleaseIterator(iter);
270+
return NULL;
271+
}
272+
}
273+
listReleaseIterator(iter);
274+
return copy;
275+
}
276+
277+
/* Search the list for a node matching a given key.
278+
* The match is performed using the 'match' method
279+
* set with listSetMatchMethod(). If no 'match' method
280+
* is set, the 'value' pointer of every node is directly
281+
* compared with the 'key' pointer.
282+
*
283+
* On success the first matching node pointer is returned
284+
* (search starts from head). If no matching node exists
285+
* NULL is returned. */
286+
listNode *listSearchKey(list *list, void *key)
287+
{
288+
listIter *iter;
289+
listNode *node;
290+
291+
iter = listGetIterator(list, AL_START_HEAD);
292+
while((node = listNext(iter)) != NULL) {
293+
if (list->match) {
294+
if (list->match(node->value, key)) {
295+
listReleaseIterator(iter);
296+
return node;
297+
}
298+
} else {
299+
if (key == node->value) {
300+
listReleaseIterator(iter);
301+
return node;
302+
}
303+
}
304+
}
305+
listReleaseIterator(iter);
306+
return NULL;
307+
}
308+
309+
/* Return the element at the specified zero-based index
310+
* where 0 is the head, 1 is the element next to head
311+
* and so on. Negative integers are used in order to count
312+
* from the tail, -1 is the last element, -2 the penultimate
313+
* and so on. If the index is out of range NULL is returned. */
314+
listNode *listIndex(list *list, long index) {
315+
listNode *n;
316+
317+
if (index < 0) {
318+
index = (-index)-1;
319+
n = list->tail;
320+
while(index-- && n) n = n->prev;
321+
} else {
322+
n = list->head;
323+
while(index-- && n) n = n->next;
324+
}
325+
return n;
326+
}
327+
328+
listNode *listGetRandomNode(list *list){
329+
unsigned long len;
330+
unsigned int index;
331+
332+
len = listLength(list);
333+
if (len <= 0) return NULL;
334+
335+
listNode *ln = NULL;
336+
listIter li;
337+
338+
listRewind(list,&li);
339+
340+
index = random() % len;
341+
while((ln = listNext(&li)) != NULL && index -- ){
342+
}
343+
return ln;
344+
}
345+
346+
/* Rotate the list removing the tail node and inserting it to the head. */
347+
void listRotate(list *list) {
348+
listNode *tail = list->tail;
349+
350+
if (listLength(list) <= 1) return;
351+
352+
/* Detach current tail */
353+
list->tail = tail->prev;
354+
list->tail->next = NULL;
355+
/* Move it as head */
356+
list->head->prev = tail;
357+
tail->prev = NULL;
358+
tail->next = list->head;
359+
list->head = tail;
360+
}

0 commit comments

Comments
 (0)