#include "gw-config.h"#include <string.h>#include <unistd.h>#include <stdlib.h>#include <errno.h>#include "gwassert.h"#include "list.h"#include "log.h"#include "thread.h"#include "gwmem.h"Include dependency graph for list.c:

Go to the source code of this file.
Data Structures | |
| struct | List |
Defines | |
| #define | INDEX(list, i) (((list)->start + i) % (list)->tab_size) |
| #define | GET(list, i) ((list)->tab[INDEX(list, i)]) |
Functions | |
| long | gwthread_self (void) |
| void | lock (List *list) |
| void | unlock (List *list) |
| void | make_bigger (List *list, long items) |
| void | delete_items_from_list (List *list, long pos, long count) |
| List * | gwlist_create_real (void) |
| void | gwlist_destroy (List *list, gwlist_item_destructor_t *destructor) |
| long | gwlist_len (List *list) |
| void | gwlist_append (List *list, void *item) |
| void | gwlist_append_unique (List *list, void *item, int(*cmp)(void *, void *)) |
| void | gwlist_insert (List *list, long pos, void *item) |
| void | gwlist_delete (List *list, long pos, long count) |
| long | gwlist_delete_matching (List *list, void *pat, gwlist_item_matches_t *matches) |
| long | gwlist_delete_equal (List *list, void *item) |
| void * | gwlist_get (List *list, long pos) |
| void * | gwlist_extract_first (List *list) |
| List * | gwlist_extract_matching (List *list, void *pat, gwlist_item_matches_t *cmp) |
| void | gwlist_lock (List *list) |
| void | gwlist_unlock (List *list) |
| int | gwlist_wait_until_nonempty (List *list) |
| void | gwlist_add_producer (List *list) |
| int | gwlist_producer_count (List *list) |
| void | gwlist_remove_producer (List *list) |
| void | gwlist_produce (List *list, void *item) |
| void * | gwlist_consume (List *list) |
| void * | gwlist_timed_consume (List *list, long sec) |
| void * | gwlist_search (List *list, void *pattern, int(*cmp)(void *, void *)) |
| List * | gwlist_search_all (List *list, void *pattern, int(*cmp)(void *, void *)) |
| void | gwlist_sort (List *list, int(*cmp)(const void *, const void *)) |
|
|
Definition at line 115 of file list.c. Referenced by gwlist_append_unique(), gwlist_consume(), gwlist_delete_equal(), gwlist_delete_matching(), gwlist_extract_first(), gwlist_extract_matching(), gwlist_get(), gwlist_insert(), gwlist_search(), gwlist_search_all(), gwlist_sort(), and gwlist_timed_consume(). |
|
|
Definition at line 114 of file list.c. Referenced by delete_items_from_list(), gwlist_append(), gwlist_append_unique(), and gwlist_insert(). |
|
||||||||||||||||
|
Definition at line 629 of file list.c. References gw_assert, INDEX, List::len, List::start, List::tab, and List::tab_size. Referenced by gwlist_consume(), gwlist_delete(), gwlist_delete_equal(), gwlist_delete_matching(), gwlist_extract_first(), gwlist_extract_matching(), and gwlist_timed_consume(). 00630 {
00631 long i, from, to;
00632
00633 gw_assert(pos >= 0);
00634 gw_assert(pos < list->len);
00635 gw_assert(count >= 0);
00636 gw_assert(pos + count <= list->len);
00637
00638 /*
00639 * There are four cases:
00640 *
00641 * Case 1: Deletion at beginning of list. Just move start
00642 * marker forwards (wrapping it at end of array). No need
00643 * to move any items.
00644 *
00645 * Case 2: Deletion at end of list. Just shorten the length
00646 * of the list. No need to move any items.
00647 *
00648 * Case 3: Deletion in the middle so that the list does not
00649 * wrap in the array. Move remaining items at end of list
00650 * to the place of the deletion.
00651 *
00652 * Case 4: Deletion in the middle so that the list does indeed
00653 * wrap in the array. Move as many remaining items at the end
00654 * of the list as will fit to the end of the array, then move
00655 * the rest to the beginning of the array.
00656 */
00657 if (pos == 0) {
00658 list->start = (list->start + count) % list->tab_size;
00659 list->len -= count;
00660 } else if (pos + count == list->len) {
00661 list->len -= count;
00662 } else if (list->start + list->len < list->tab_size) {
00663 memmove(list->tab + list->start + pos,
00664 list->tab + list->start + pos + count,
00665 (list->len - pos - count) * sizeof(void *));
00666 list->len -= count;
00667 } else {
00668 /*
00669 * This is not specially efficient, but it's simple and
00670 * works. Faster methods would have to take more special
00671 * cases into account.
00672 */
00673 for (i = 0; i < list->len - count - pos; ++i) {
00674 from = INDEX(list, pos + i + count);
00675 to = INDEX(list, pos + i);
00676 list->tab[to] = list->tab[from];
00677 }
00678 list->len -= count;
00679 }
00680 }
|
|
|
||||||||||||
Here is the call graph for this function:

|
||||||||||||||||
|
Definition at line 187 of file list.c. References GET, INDEX, List::len, lock, make_bigger(), List::nonempty, List::tab, and unlock. 00188 {
00189 void *it;
00190 long i;
00191
00192 lock(list);
00193 it = NULL;
00194 for (i = 0; i < list->len; ++i) {
00195 it = GET(list, i);
00196 if (cmp(it, item)) {
00197 break;
00198 }
00199 }
00200 if (i == list->len) {
00201 /* not yet in list, so add it */
00202 make_bigger(list, 1);
00203 list->tab[INDEX(list, list->len)] = item;
00204 ++list->len;
00205 pthread_cond_signal(&list->nonempty);
00206 }
00207 unlock(list);
00208 }
|
Here is the call graph for this function:

|
Here is the call graph for this function:

|
|
Definition at line 126 of file list.c. References List::len, mutex_create, List::nonempty, List::num_producers, List::permanent_lock, List::single_operation_lock, List::start, List::tab, and List::tab_size. 00127 {
00128 List *list;
00129
00130 list = gw_malloc(sizeof(List));
00131 list->tab = NULL;
00132 list->tab_size = 0;
00133 list->start = 0;
00134 list->len = 0;
00135 list->single_operation_lock = mutex_create();
00136 list->permanent_lock = mutex_create();
00137 pthread_cond_init(&list->nonempty, NULL);
00138 list->num_producers = 0;
00139 return list;
00140 }
|
|
||||||||||||||||
|
Definition at line 229 of file list.c. References delete_items_from_list(), lock, and unlock. Referenced by dbpool_check(), dlr_mem_flush(), dlr_mem_remove(), expire_cookies(), have_cookie(), http_header_pack(), http_header_remove_all(), http_header_split_auth_value(), main_for_producer_and_consumer(), mime_entity_remove_part(), mime_entity_replace_part(), pack_challenge(), sanitize_capabilities(), smsc2_restart_smsc(), soap_client_init_query(), and strip_default_capabilities(). 00230 {
00231 lock(list);
00232 delete_items_from_list(list, pos, count);
00233 unlock(list);
00234 }
|
Here is the call graph for this function:

|
||||||||||||
|
Definition at line 263 of file list.c. References delete_items_from_list(), GET, List::len, lock, and unlock. Referenced by abort_elapsed(), check_pool_conn(), client_destroy(), handle_method_event(), handle_push_event(), init_machine_destroy(), machine_destroy(), main_for_list_add_and_delete(), push_client_machine_destroy(), remove_push_data(), remove_pushless_session(), remove_session_data(), resp_machine_destroy(), route_msg(), run_smsbox(), run_wapbox(), update_push_data_with_attribute(), and update_session_data(). 00264 {
00265 long i;
00266 long count;
00267
00268 lock(list);
00269
00270 /* XXX this could be made more efficient by noticing
00271 consecutive items to be removed, but leave that for later.
00272 --liw */
00273 i = 0;
00274 count = 0;
00275 while (i < list->len) {
00276 if (GET(list, i) == item) {
00277 delete_items_from_list(list, i, 1);
00278 count++;
00279 } else {
00280 ++i;
00281 }
00282 }
00283 unlock(list);
00284
00285 return count;
00286 }
|
Here is the call graph for this function:

|
||||||||||||||||
|
Definition at line 237 of file list.c. References delete_items_from_list(), GET, List::len, lock, and unlock. Referenced by main_for_list_add_and_delete(), smsbox_req_handle(), update_push_data_with_attribute(), and update_session_data_with_headers(). 00238 {
00239 long i;
00240 long count;
00241
00242 lock(list);
00243
00244 /* XXX this could be made more efficient by noticing
00245 consecutive items to be removed, but leave that for later.
00246 --liw */
00247 i = 0;
00248 count = 0;
00249 while (i < list->len) {
00250 if (matches(GET(list, i), pat)) {
00251 delete_items_from_list(list, i, 1);
00252 count++;
00253 } else {
00254 ++i;
00255 }
00256 }
00257 unlock(list);
00258
00259 return count;
00260 }
|
Here is the call graph for this function:

|
||||||||||||
Here is the call graph for this function:

|
Here is the call graph for this function:

|
||||||||||||||||
|
Definition at line 319 of file list.c. References delete_items_from_list(), GET, gwlist_append(), gwlist_create, gwlist_destroy(), gwlist_len(), List::len, lock, and unlock. Referenced by dict_remove(), heartbeat_stop(), and main_for_extract(). 00320 {
00321 List *new_list;
00322 long i;
00323
00324 new_list = gwlist_create();
00325 lock(list);
00326 i = 0;
00327 while (i < list->len) {
00328 if (cmp(GET(list, i), pat)) {
00329 gwlist_append(new_list, GET(list, i));
00330 delete_items_from_list(list, i, 1);
00331 } else
00332 ++i;
00333 }
00334 unlock(list);
00335
00336 if (gwlist_len(new_list) == 0) {
00337 gwlist_destroy(new_list, NULL);
00338 return NULL;
00339 }
00340 return new_list;
00341 }
|
Here is the call graph for this function:

|
||||||||||||
|
||||||||||||||||
|
Definition at line 211 of file list.c. References GET, gw_assert, INDEX, List::len, lock, make_bigger(), List::nonempty, List::tab, and unlock. Referenced by cfg_read(), expand_file(), handle_transaction(), http_header_pack(), machine_create(), mime_entity_replace_part(), parse_limit(), sms_to_smsboxes(), and smsc2_restart_smsc(). 00212 {
00213 long i;
00214
00215 lock(list);
00216 gw_assert(pos >= 0);
00217 gw_assert(pos <= list->len);
00218
00219 make_bigger(list, 1);
00220 for (i = list->len; i > pos; --i)
00221 list->tab[INDEX(list, i)] = GET(list, i - 1);
00222 list->tab[INDEX(list, pos)] = item;
00223 ++list->len;
00224 pthread_cond_signal(&list->nonempty);
00225 unlock(list);
00226 }
|
Here is the call graph for this function:

|
|
|
Definition at line 344 of file list.c. References gw_assert, mutex_lock, and List::permanent_lock. Referenced by alog(), alog_close(), alog_reopen(), boxc_incoming_wdp_queue(), boxc_status(), client_destroy(), dbpool_check(), dbpool_conn_consume(), dbpool_decrease(), dbpool_increase(), gw_rwlock_rdlock(), gw_rwlock_wrlock(), port_remove(), route_msg(), run_wapbox(), set_tid_by_item(), soap_client_have_response(), soap_client_init_query(), udp_addwdp(), udp_outgoing_queue(), udpc_find_mapping(), wdp_to_wapboxes(), and xmlrpc_call_print(). 00345 {
00346 gw_assert(list != NULL);
00347 mutex_lock(list->permanent_lock);
00348 }
|
|
||||||||||||
Here is the call graph for this function:

|
|
Definition at line 386 of file list.c. References lock, List::num_producers, and unlock. Referenced by gw_rwlock_wrlock(), main(), run_smsbox(), run_wapbox(), and sms_to_smsboxes(). 00387 {
00388 int ret;
00389 lock(list);
00390 ret = list->num_producers;
00391 unlock(list);
00392 return ret;
00393 }
|
|
|
||||||||||||||||
|
Definition at line 463 of file list.c. References GET, List::len, lock, and unlock. 00464 {
00465 void *item;
00466 long i;
00467
00468 lock(list);
00469 item = NULL;
00470 for (i = 0; i < list->len; ++i) {
00471 item = GET(list, i);
00472 if (cmp(item, pattern)) {
00473 break;
00474 }
00475 }
00476 if (i == list->len) {
00477 item = NULL;
00478 }
00479 unlock(list);
00480
00481 return item;
00482 }
|
|
||||||||||||||||
|
Definition at line 486 of file list.c. References GET, gwlist_append(), gwlist_create, gwlist_destroy(), gwlist_len(), List::len, lock, and unlock. 00487 {
00488 List *new_list;
00489 void *item;
00490 long i;
00491
00492 new_list = gwlist_create();
00493
00494 lock(list);
00495 item = NULL;
00496 for (i = 0; i < list->len; ++i) {
00497 item = GET(list, i);
00498 if (cmp(item, pattern))
00499 gwlist_append(new_list, item);
00500 }
00501 unlock(list);
00502
00503 if (gwlist_len(new_list) == 0) {
00504 gwlist_destroy(new_list, NULL);
00505 new_list = NULL;
00506 }
00507
00508 return new_list;
00509 }
|
Here is the call graph for this function:

|
||||||||||||
|
Definition at line 512 of file list.c. References GET, gw_assert, List::len, lock, and unlock. Referenced by main(). 00513 {
00514 gw_assert(list != NULL && cmp != NULL);
00515
00516 lock(list);
00517 if (list->len == 0) {
00518 /* nothing to sort */
00519 unlock(list);
00520 return;
00521 }
00522 qsort(&GET(list, 0), list->len, sizeof(void*), cmp);
00523 unlock(list);
00524 }
|
|
||||||||||||
|
Definition at line 434 of file list.c. References delete_items_from_list(), GET, gwthread_self(), List::len, lock, Mutex::mutex, List::nonempty, List::num_producers, Mutex::owner, List::single_operation_lock, and unlock. Referenced by sms_router(). 00435 {
00436 void *item;
00437 struct timespec abstime;
00438 int rc;
00439
00440 abstime.tv_sec = time(NULL) + sec;
00441 abstime.tv_nsec = 0;
00442
00443 lock(list);
00444 while (list->len == 0 && list->num_producers > 0) {
00445 list->single_operation_lock->owner = -1;
00446 rc = pthread_cond_timedwait(&list->nonempty,
00447 &list->single_operation_lock->mutex, &abstime);
00448 list->single_operation_lock->owner = gwthread_self();
00449 if (rc == ETIMEDOUT)
00450 break;
00451 }
00452 if (list->len > 0) {
00453 item = GET(list, 0);
00454 delete_items_from_list(list, 0, 1);
00455 } else {
00456 item = NULL;
00457 }
00458 unlock(list);
00459 return item;
00460 }
|
Here is the call graph for this function:

|
|
Definition at line 351 of file list.c. References gw_assert, mutex_unlock, and List::permanent_lock. Referenced by alog(), alog_close(), alog_reopen(), boxc_incoming_wdp_queue(), boxc_status(), client_destroy(), dbpool_check(), dbpool_conn_consume(), dbpool_decrease(), dbpool_increase(), gw_rwlock_rdlock(), gw_rwlock_unlock(), port_remove(), route_msg(), run_wapbox(), set_tid_by_item(), soap_client_have_response(), soap_client_init_query(), udp_addwdp(), udp_outgoing_queue(), udpc_find_mapping(), wdp_to_wapboxes(), and xmlrpc_call_print(). 00352 {
00353 gw_assert(list != NULL);
00354 mutex_unlock(list->permanent_lock);
00355 }
|
|
|
Definition at line 358 of file list.c. References gwthread_self(), List::len, lock, Mutex::mutex, List::nonempty, List::num_producers, Mutex::owner, List::single_operation_lock, and unlock. Referenced by smsboxc_run(), wait_for_connections(), and wapboxc_run(). 00359 {
00360 int ret;
00361
00362 lock(list);
00363 while (list->len == 0 && list->num_producers > 0) {
00364 list->single_operation_lock->owner = -1;
00365 pthread_cond_wait(&list->nonempty,
00366 &list->single_operation_lock->mutex);
00367 list->single_operation_lock->owner = gwthread_self();
00368 }
00369 if (list->len > 0)
00370 ret = 1;
00371 else
00372 ret = -1;
00373 unlock(list);
00374 return ret;
00375 }
|
Here is the call graph for this function:

|
|
Definition at line 626 of file gwthread-pthread.c. References threadinfo::number, and tsd_key. Referenced by client_thread(), conn_claim(), fdset_destroy(), fdset_listen(), fdset_register(), fdset_set_timeout(), fdset_unregister(), find_entry(), gw_prioqueue_consume(), gw_rwlock_unlock(), gw_rwlock_wrlock(), gwlist_consume(), gwlist_timed_consume(), gwlist_wait_until_nonempty(), gwthread_create_real(), gwthread_join_all(), gwthread_wakeup_all(), handle_action(), lock_in(), lock_out(), mutex_lock_real(), mutex_trylock_real(), new_thread(), openssl_init_locks(), producer(), and push_thread(). 00627 {
00628 struct threadinfo *threadinfo;
00629 threadinfo = pthread_getspecific(tsd_key);
00630 if (threadinfo)
00631 return threadinfo->number;
00632 else
00633 return -1;
00634 }
|
|
|
Definition at line 529 of file list.c. References gw_assert, mutex_lock, and List::single_operation_lock. 00530 {
00531 gw_assert(list != NULL);
00532 mutex_lock(list->single_operation_lock);
00533 }
|
|
||||||||||||
|
Definition at line 548 of file list.c. References gw_assert, List::len, List::start, List::tab, and List::tab_size. Referenced by gw_prioqueue_create(), gw_prioqueue_insert(), gwlist_append(), gwlist_append_unique(), and gwlist_insert(). 00549 {
00550 long old_size, new_size;
00551 long len_at_beginning, len_at_end;
00552
00553 if (list->len + items <= list->tab_size)
00554 return;
00555
00556 old_size = list->tab_size;
00557 new_size = old_size + items;
00558 list->tab = gw_realloc(list->tab, new_size * sizeof(void *));
00559 list->tab_size = new_size;
00560
00561 /*
00562 * Now, one of the following situations is in effect
00563 * (* is used, empty is unused element):
00564 *
00565 * Case 1: Used area did not wrap. No action is necessary.
00566 *
00567 * old_size new_size
00568 * v v
00569 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
00570 * | |*|*|*|*|*|*| | | | | | | | | | | | | | | | |
00571 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
00572 * ^ ^
00573 * start start+len
00574 *
00575 * Case 2: Used area wrapped, but the part at the beginning
00576 * of the array fits into the new area. Action: move part
00577 * from beginning to new area.
00578 *
00579 * old_size new_size
00580 * v v
00581 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
00582 * |*|*| | | | | | | |*|*|*| | | | | | | | | | | |
00583 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
00584 * ^ ^
00585 * start+len start
00586 *
00587 * Case 3: Used area wrapped, and the part at the beginning
00588 * of the array does not fit into the new area. Action: move
00589 * as much as will fit from beginning to new area and move
00590 * the rest to the beginning.
00591 *
00592 * old_size new_size
00593 * v v
00594 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
00595 * |*|*|*|*|*|*|*|*|*| | | | | | | | |*|*|*|*| | |
00596 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
00597 * ^ ^
00598 * start+len start
00599 */
00600
00601 gw_assert(list->start < old_size ||
00602 (list->start == 0 && old_size == 0));
00603 if (list->start + list->len > old_size) {
00604 len_at_end = old_size - list->start;
00605 len_at_beginning = list->len - len_at_end;
00606 if (len_at_beginning <= new_size - old_size) {
00607 /* This is Case 2. */
00608 memmove(list->tab + old_size,
00609 list->tab,
00610 len_at_beginning * sizeof(void *));
00611 } else {
00612 /* This is Case 3. */
00613 memmove(list->tab + old_size,
00614 list->tab,
00615 (new_size - old_size) * sizeof(void *));
00616 memmove(list->tab,
00617 list->tab + (new_size - old_size),
00618 (len_at_beginning - (new_size - old_size))
00619 * sizeof(void *));
00620 }
00621 }
00622 }
|
|
|
Definition at line 535 of file list.c. References gw_assert, mutex_unlock, and List::single_operation_lock. 00536 {
00537 gw_assert(list != NULL);
00538 mutex_unlock(list->single_operation_lock);
00539 }
|