Kannel: Open Source WAP and SMS gateway  svn-r5335
list.c File Reference
#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"

Go to the source code of this file.

Data Structures

struct  List
 

Macros

#define INDEX(list, i)   (((list)->start + i) % (list)->tab_size)
 
#define GET(list, i)   ((list)->tab[INDEX(list, i)])
 

Functions

long gwthread_self (void)
 
static void lock (List *list)
 
static void unlock (List *list)
 
static void make_bigger (List *list, long items)
 
static void delete_items_from_list (List *list, long pos, long count)
 
Listgwlist_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)
 
Listgwlist_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)
 
int gwlist_consumer_count (List *list)
 
void * gwlist_consume (List *list)
 
void * gwlist_timed_consume (List *list, long sec)
 
void * gwlist_search (List *list, void *pattern, int(*cmp)(void *, void *))
 
Listgwlist_search_all (List *list, void *pattern, int(*cmp)(void *, void *))
 
long gwlist_search_equal (List *list, void *item)
 
static void quicksort (List *list, long left, long right, int(*cmp)(const void *, const void *))
 
void gwlist_sort (List *list, int(*cmp)(const void *, const void *))
 

Macro Definition Documentation

◆ GET

◆ INDEX

#define INDEX (   list,
 
)    (((list)->start + i) % (list)->tab_size)

Definition at line 115 of file list.c.

Referenced by delete_items_from_list(), gwlist_append(), gwlist_append_unique(), and gwlist_insert().

Function Documentation

◆ delete_items_from_list()

static void delete_items_from_list ( List list,
long  pos,
long  count 
)
static

Definition at line 693 of file list.c.

References from, 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().

694 {
695  long i, from, to;
696 
697  gw_assert(pos >= 0);
698  gw_assert(pos < list->len);
699  gw_assert(count >= 0);
700  gw_assert(pos + count <= list->len);
701 
702  /*
703  * There are four cases:
704  *
705  * Case 1: Deletion at beginning of list. Just move start
706  * marker forwards (wrapping it at end of array). No need
707  * to move any items.
708  *
709  * Case 2: Deletion at end of list. Just shorten the length
710  * of the list. No need to move any items.
711  *
712  * Case 3: Deletion in the middle so that the list does not
713  * wrap in the array. Move remaining items at end of list
714  * to the place of the deletion.
715  *
716  * Case 4: Deletion in the middle so that the list does indeed
717  * wrap in the array. Move as many remaining items at the end
718  * of the list as will fit to the end of the array, then move
719  * the rest to the beginning of the array.
720  */
721  if (pos == 0) {
722  list->start = (list->start + count) % list->tab_size;
723  list->len -= count;
724  } else if (pos + count == list->len) {
725  list->len -= count;
726  } else if (list->start + list->len < list->tab_size) {
727  memmove(list->tab + list->start + pos,
728  list->tab + list->start + pos + count,
729  (list->len - pos - count) * sizeof(void *));
730  list->len -= count;
731  } else {
732  /*
733  * This is not specially efficient, but it's simple and
734  * works. Faster methods would have to take more special
735  * cases into account.
736  */
737  for (i = 0; i < list->len - count - pos; ++i) {
738  from = INDEX(list, pos + i + count);
739  to = INDEX(list, pos + i);
740  list->tab[to] = list->tab[from];
741  }
742  list->len -= count;
743  }
744 }
gw_assert(wtls_machine->packet_to_send !=NULL)
static Octstr * from
Definition: mtbatch.c:95
long len
Definition: list.c:107
long tab_size
Definition: list.c:105
long start
Definition: list.c:106
void ** tab
Definition: list.c:104
#define INDEX(list, i)
Definition: list.c:115

◆ gwlist_add_producer()

◆ gwlist_append()

void gwlist_append ( List list,
void *  item 
)

Definition at line 179 of file list.c.

References INDEX, List::len, lock(), make_bigger(), List::nonempty, List::tab, and unlock().

Referenced by add_cookie_to_cache(), add_group(), add_sar_transaction(), add_service(), add_tid(), at2_wait_modem_command(), attr_dict_construct(), boxc_receiver(), cfg_add_hooks(), cfg_get_group_checksum(), cfg_get_multi_group(), cfg_init(), check_data_content_type_header(), check_data_x_wap_application_id_header(), check_do_elements(), check_multipart(), cimd2_handle_request(), client_done(), client_thread(), dict_keys(), dict_put(), dict_put_true(), dict_traverse_sorted(), dispatch_into_queue(), dlr_mem_add(), expand_file(), get_matching_translations(), get_x_kannel_from_xml(), gw_timer_break(), gwlist_extract_matching(), gwlist_produce(), gwlist_search_all(), gwthread_join(), gwthread_join_every(), handle_submit(), heartbeat_start(), http_append_headers(), http_header_add(), http_header_add_element(), http_header_duplicate(), http_header_find_all(), http_thread(), http_use_proxy(), init_machine_create(), init_reroute(), initialize_clients(), main(), main_for_extract(), main_for_list_add_and_delete(), method_machine_create(), mime_entity_add_part(), mime_entity_duplicate(), mime_something_to_entity(), msg_to_pdu(), octstr_split(), octstr_split_words(), oisd_handle_request(), oneuser_add(), parse_cgivars(), parse_data_element(), parse_param_element(), pass_data_headers(), push_client_machine_create(), push_machine_create(), read_mime_headers(), read_some_headers(), refuse_unreplied_capabilities(), reply_known_capabilities(), resp_machine_create(), run_smppbox(), run_smsbox(), run_wapbox(), send_message(), session_machine_create(), set_cookies(), sms_split(), smsbox_req_handle(), smsc2_add_smsc(), smsc2_graceful_restart(), smsc2_start(), soap_add_msg_cb(), soap_client_init_query(), soap_create_map(), split_headers(), store_push_data(), string_table_add(), string_table_add_many(), string_table_collect_strings(), string_table_collect_words(), string_table_sort_list(), submit_action(), submit_action_nosync(), update_push_data_with_attribute(), update_session_data(), update_session_data_with_headers(), urltrans_add_one(), wap_map_add_url(), wml_charsets(), wml_init(), wsp_cap_duplicate_list(), wsp_cap_unpack_list(), wsp_strip_parameters(), wtp_pdu_append_tpi(), and wtp_unpack_wdp_datagram().

180 {
181  lock(list);
182  make_bigger(list, 1);
183  list->tab[INDEX(list, list->len)] = item;
184  ++list->len;
185  pthread_cond_signal(&list->nonempty);
186  unlock(list);
187 }
static void lock(List *list)
Definition: list.c:593
long len
Definition: list.c:107
static void unlock(List *list)
Definition: list.c:599
pthread_cond_t nonempty
Definition: list.c:110
void ** tab
Definition: list.c:104
static void make_bigger(List *list, long items)
Definition: list.c:612
#define INDEX(list, i)
Definition: list.c:115

◆ gwlist_append_unique()

void gwlist_append_unique ( List list,
void *  item,
int(*)(void *, void *)  cmp 
)

Definition at line 190 of file list.c.

References GET, INDEX, List::len, lock(), make_bigger(), List::nonempty, List::tab, and unlock().

Referenced by smsbox_req_handle().

191 {
192  void *it;
193  long i;
194 
195  lock(list);
196  it = NULL;
197  for (i = 0; i < list->len; ++i) {
198  it = GET(list, i);
199  if (cmp(it, item)) {
200  break;
201  }
202  }
203  if (i == list->len) {
204  /* not yet in list, so add it */
205  make_bigger(list, 1);
206  list->tab[INDEX(list, list->len)] = item;
207  ++list->len;
208  pthread_cond_signal(&list->nonempty);
209  }
210  unlock(list);
211 }
static void lock(List *list)
Definition: list.c:593
long len
Definition: list.c:107
static void unlock(List *list)
Definition: list.c:599
pthread_cond_t nonempty
Definition: list.c:110
void ** tab
Definition: list.c:104
static void make_bigger(List *list, long items)
Definition: list.c:612
#define INDEX(list, i)
Definition: list.c:115
#define GET(list, i)
Definition: list.c:116

◆ gwlist_consume()

void* gwlist_consume ( List list)

Definition at line 427 of file list.c.

References delete_items_from_list(), GET, gwthread_self(), List::len, lock(), Mutex::mutex, List::nonempty, List::num_consumers, List::num_producers, Mutex::owner, List::single_operation_lock, and unlock().

Referenced by alog_close(), alog_reopen(), boxc_receiver(), boxc_sender(), cimd2_receive_msg(), consumer(), dict_traverse_sorted(), eq_extract(), gw_rwlock_wrlock(), http_queue_thread(), http_receive_result_real(), http_remove_hop_headers(), httpsmsc_sender(), io_thread(), main(), main_thread(), meta_data_merge(), obey_request_thread(), oisd_receive_msg(), ota_read_thread(), pack_cache_control(), pap_request_thread(), parse_methodresponse_element(), port_get_request(), retry_consumer_thread(), run_batch(), semaphore_down(), server_thread(), service_router(), sms_to_smsboxes(), sql_list(), store_file_save(), store_spool_save(), submit_action(), timer_consumer_thread(), udp_die(), udp_receiver(), udp_sender(), wait_for_connections(), wapboxc_run(), wdp_router(), wdp_to_wapboxes(), wrapper_receiver(), wrapper_sender(), write_request_thread(), wsp_pack_list(), wtp_pdu_destroy(), and xmlrpc_print_struct().

428 {
429  void *item;
430 
431  lock(list);
432  ++list->num_consumers;
433  while (list->len == 0 && list->num_producers > 0) {
434  list->single_operation_lock->owner = -1;
435  pthread_cleanup_push((void(*)(void*))pthread_mutex_unlock, &list->single_operation_lock->mutex);
436  pthread_cond_wait(&list->nonempty,
437  &list->single_operation_lock->mutex);
438  pthread_cleanup_pop(0);
440  }
441  if (list->len > 0) {
442  item = GET(list, 0);
443  delete_items_from_list(list, 0, 1);
444  } else {
445  item = NULL;
446  }
447  --list->num_consumers;
448  unlock(list);
449  return item;
450 }
long num_consumers
Definition: list.c:112
static void lock(List *list)
Definition: list.c:593
long len
Definition: list.c:107
static void unlock(List *list)
Definition: list.c:599
pthread_mutex_t mutex
Definition: thread.h:77
Mutex * single_operation_lock
Definition: list.c:108
static void delete_items_from_list(List *list, long pos, long count)
Definition: list.c:693
long gwthread_self(void)
pthread_cond_t nonempty
Definition: list.c:110
long num_producers
Definition: list.c:111
long owner
Definition: thread.h:78
#define GET(list, i)
Definition: list.c:116

◆ gwlist_consumer_count()

int gwlist_consumer_count ( List list)

Definition at line 417 of file list.c.

References lock(), List::num_consumers, and unlock().

418 {
419  int ret;
420  lock(list);
421  ret = list->num_consumers;
422  unlock(list);
423  return ret;
424 }
long num_consumers
Definition: list.c:112
static void lock(List *list)
Definition: list.c:593
static void unlock(List *list)
Definition: list.c:599

◆ gwlist_create_real()

List* gwlist_create_real ( void  )

Definition at line 127 of file list.c.

References List::len, mutex_create, List::nonempty, List::num_consumers, List::num_producers, List::permanent_lock, List::single_operation_lock, List::start, List::tab, and List::tab_size.

128 {
129  List *list;
130 
131  list = gw_malloc(sizeof(List));
132  list->tab = NULL;
133  list->tab_size = 0;
134  list->start = 0;
135  list->len = 0;
137  list->permanent_lock = mutex_create();
138  pthread_cond_init(&list->nonempty, NULL);
139  list->num_producers = 0;
140  list->num_consumers = 0;
141  return list;
142 }
long num_consumers
Definition: list.c:112
#define mutex_create()
Definition: thread.h:96
long len
Definition: list.c:107
long tab_size
Definition: list.c:105
Mutex * single_operation_lock
Definition: list.c:108
pthread_cond_t nonempty
Definition: list.c:110
long start
Definition: list.c:106
Mutex * permanent_lock
Definition: list.c:109
void ** tab
Definition: list.c:104
long num_producers
Definition: list.c:111
Definition: list.c:102

◆ gwlist_delete()

void gwlist_delete ( List list,
long  pos,
long  count 
)

◆ gwlist_delete_equal()

long gwlist_delete_equal ( List list,
void *  item 
)

Definition at line 266 of file list.c.

References delete_items_from_list(), GET, lock(), and unlock().

Referenced by abort_elapsed(), boxc_receiver(), cfg_get_group_checksum(), 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_smppbox(), run_smsbox(), run_wapbox(), update_push_data_with_attribute(), and update_session_data().

267 {
268  long i;
269  long count;
270 
271  lock(list);
272 
273  /* XXX this could be made more efficient by noticing
274  consecutive items to be removed, but leave that for later.
275  --liw */
276  i = 0;
277  count = 0;
278  while (i < list->len) {
279  if (GET(list, i) == item) {
280  delete_items_from_list(list, i, 1);
281  count++;
282  } else {
283  ++i;
284  }
285  }
286  unlock(list);
287 
288  return count;
289 }
static void lock(List *list)
Definition: list.c:593
static void unlock(List *list)
Definition: list.c:599
static void delete_items_from_list(List *list, long pos, long count)
Definition: list.c:693
#define GET(list, i)
Definition: list.c:116

◆ gwlist_delete_matching()

long gwlist_delete_matching ( List list,
void *  pat,
gwlist_item_matches_t matches 
)

Definition at line 240 of file list.c.

References delete_items_from_list(), GET, 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().

241 {
242  long i;
243  long count;
244 
245  lock(list);
246 
247  /* XXX this could be made more efficient by noticing
248  consecutive items to be removed, but leave that for later.
249  --liw */
250  i = 0;
251  count = 0;
252  while (i < list->len) {
253  if (matches(GET(list, i), pat)) {
254  delete_items_from_list(list, i, 1);
255  count++;
256  } else {
257  ++i;
258  }
259  }
260  unlock(list);
261 
262  return count;
263 }
static void lock(List *list)
Definition: list.c:593
static void unlock(List *list)
Definition: list.c:599
static void delete_items_from_list(List *list, long pos, long count)
Definition: list.c:693
#define GET(list, i)
Definition: list.c:116

◆ gwlist_destroy()

void gwlist_destroy ( List list,
gwlist_item_destructor_t destructor 
)

Definition at line 145 of file list.c.

References gwlist_extract_first(), gwlist_len(), mutex_destroy(), List::nonempty, List::permanent_lock, List::single_operation_lock, and List::tab.

Referenced by action_destroy(), add_group(), alog_close(), at2_detect_modem_type(), at2_device_thread(), at2_init_device(), at2_read_modems(), attribute_destroy(), bb_reload_smsc_groups(), bearerbox_to_smpp(), boxc_gwlist_destroy(), brunet_parse_body(), cfg_dump(), cfg_get_group_checksum(), cfg_read(), cfg_shutdown(), cgw_sender(), check_do_elements(), cimd2_destroy(), clickatell_parse_body(), client_is_persistent(), client_shutdown(), client_thread(), concat_handling_clear_old_parts(), config_reload(), conn_pool_item_destroy(), conndata_destroy(), cookies_destroy(), create_onetrans(), delete_threadinfo(), destroy_clients(), destroy_group_list(), destroy_keyword_list(), destroy_methodmachines(), destroy_onetrans(), destroy_pushmachines(), destroy_users_list(), dict_destroy(), dict_remove(), dict_traverse_sorted(), disconnect_other_sessions(), dispatch_datagram(), dlr_mem_shutdown(), do_dump(), do_queue_cleanup(), empty_msg_lists(), eq_destroy(), expand_file(), fake_listener(), fdset_destroy(), find_translation(), get_pattern(), grp_dump(), gw_rwlock_destroy(), gwlist_extract_matching(), gwlist_search_all(), handle_pdu(), handle_submit(), heartbeat_stop(), http_caller_destroy(), http_close_proxy(), http_destroy_cgiargs(), http_destroy_headers(), http_remove_hop_headers(), init_bearerbox(), init_reroute(), init_smsbox(), init_smsbox_routes(), init_smsc_routes(), io_thread(), main(), main_for_extract(), main_for_list_add_and_delete(), meta_data_merge(), meta_data_pack(), meta_data_set_values(), mime_entity_destroy(), msg_to_pdu(), oisd_destroy(), pack_accept(), pack_accept_charset(), pack_accept_encoding(), pack_accept_language(), pack_cache_control(), pack_challenge(), pack_content_disposition(), pack_credentials(), pack_known_header(), parse_context_destroy(), parse_methodresponse_element(), parse_request_line(), pattern_list_matches_ip(), port_remove(), port_shutdown(), prefix_allowed(), push_machines_list_destroy(), randomize(), read_ppg_config(), receive_reply(), release_holding_methods(), response(), run_batch(), run_smsbox(), run_wapbox(), semaphore_destroy(), send_message(), server_shutdown(), smasi_destroy(), smpp_destroy(), smpp_pdu_init(), smpp_pdu_shutdown(), smpp_tlv_add_constant(), smsbox_req_handle(), smsbox_req_sendota(), smsboxc_run(), smsc2_cleanup(), smsc2_graceful_restart(), smsc_cgw_create(), smsc_fake_create(), smsc_soap_create(), smscconn_destroy(), smscconn_reconfig(), smscconn_send(), smscwrapper_destroy(), soap_create_map(), soap_fetch_xml_data(), soap_listener(), soap_map_xml_data(), soap_parse_dlr(), soap_parse_mo(), soap_parse_response(), soap_release_dependences(), soap_server(), sql_list(), store_file_for_each_message(), store_file_load(), store_file_shutdown(), store_spool_shutdown(), string_table_add_many(), string_table_build(), string_table_collect_words(), string_table_sort_list(), udp_die(), udp_start(), udpc_destroy(), urltrans_add_cfg(), urltrans_destroy(), urltrans_fill_escape_codes(), wap_appl_shutdown(), wap_dispatch_datagram(), wap_map_destroy(), wap_push_ota_shutdown(), wap_push_ppg_pushuser_list_add(), wap_push_ppg_pushuser_list_destroy(), wap_push_ppg_pushuser_search_ip_from_wildcarded_list(), wap_push_ppg_shutdown(), wapboxc_run(), wdp_to_wapboxes(), wildcarded_ip_found(), wml_binary_destroy(), wml_shutdown(), wrapper_sender(), wsp_cap_destroy_list(), wsp_push_client_shutdown(), wsp_session_shutdown(), wsp_unit_shutdown(), wtp_event_dump(), wtp_initiator_shutdown(), wtp_pdu_destroy(), wtp_resp_shutdown(), wtp_tid_cache_shutdown(), xmlrpc_call_destroy(), xmlrpc_print_struct(), and xmlrpc_value_destroy().

146 {
147  long len, i;
148 
149  if (list == NULL)
150  return;
151 
152  if (destructor != NULL) {
153  len = gwlist_len(list); /* Using while(x != NULL) is unreliable, what if someone added NULL values? */
154  for (i = 0; i < len; i++)
155  destructor(gwlist_extract_first(list));
156  }
157 
160  pthread_cond_destroy(&list->nonempty);
161  gw_free(list->tab);
162  gw_free(list);
163 }
long gwlist_len(List *list)
Definition: list.c:166
void * gwlist_extract_first(List *list)
Definition: list.c:305
Mutex * single_operation_lock
Definition: list.c:108
void mutex_destroy(Mutex *mutex)
Definition: thread.c:97
pthread_cond_t nonempty
Definition: list.c:110
Mutex * permanent_lock
Definition: list.c:109
void ** tab
Definition: list.c:104

◆ gwlist_extract_first()

void* gwlist_extract_first ( List list)

Definition at line 305 of file list.c.

References delete_items_from_list(), GET, gw_assert(), List::len, lock(), and unlock().

Referenced by add_group(), alert_joiners(), at2_read_modems(), at2_read_pending_incoming_messages(), bearerbox_to_smpp(), brunet_parse_body(), cfg_dump(), cfg_get_group_checksum(), cfg_read(), cgw_open_send_connection(), cgw_send_loop(), cgw_sender(), cgw_shutdown_cb(), cimd2_shutdown_cb(), clickatell_parse_body(), concat_handling_clear_old_parts(), config_reload(), conn_pool_get(), dict_destroy(), dispatch_datagram(), do_queue_cleanup(), empty_msg_lists(), expand_file(), fake_listener(), grp_dump(), gwlist_destroy(), heartbeat_stop(), http_destroy_cgiargs(), http_receive_result_real(), httpsmsc_sender(), init_reroute(), init_smsbox_routes(), init_smsc_routes(), io_thread(), main(), main_connection_loop(), meta_data_pack(), meta_data_set_values(), msg_to_pdu(), oisd_shutdown_cb(), parse_context_destroy(), parse_pop_limit(), pattern_list_matches_ip(), poller(), port_remove(), receive_push_reply(), receive_reply(), reconnect(), run_requests(), run_smsbox(), send_message(), send_messages(), server_thread(), shutdown_cb(), smpp_pdu_init(), smpp_tlv_add_constant(), smsbox_req_handle(), smsbox_req_sendota(), smsc2_graceful_restart(), smsc_soap_create(), soap_client_init_query(), soap_create_map(), soap_listener(), soap_release_dependences(), soap_send_loop(), soap_shutdown_cb(), store_file_load(), string_table_add_many(), string_table_build(), string_table_collect_words(), string_table_output(), string_table_sort_list(), udp_start(), urltrans_add_cfg(), wap_dispatch_datagram(), wap_push_ppg_pushuser_list_add(), wdp_to_wapboxes(), wrapper_sender(), wrapper_shutdown(), and wtp_event_dump().

306 {
307  void *item;
308 
309  gw_assert(list != NULL);
310  lock(list);
311  if (list->len == 0)
312  item = NULL;
313  else {
314  item = GET(list, 0);
315  delete_items_from_list(list, 0, 1);
316  }
317  unlock(list);
318  return item;
319 }
static void lock(List *list)
Definition: list.c:593
gw_assert(wtls_machine->packet_to_send !=NULL)
long len
Definition: list.c:107
static void unlock(List *list)
Definition: list.c:599
static void delete_items_from_list(List *list, long pos, long count)
Definition: list.c:693
#define GET(list, i)
Definition: list.c:116

◆ gwlist_extract_matching()

List* gwlist_extract_matching ( List list,
void *  pat,
gwlist_item_matches_t cmp 
)

Definition at line 322 of file list.c.

References delete_items_from_list(), GET, gwlist_append(), gwlist_create, gwlist_destroy(), gwlist_len(), lock(), and unlock().

Referenced by dict_remove(), heartbeat_stop(), and main_for_extract().

323 {
324  List *new_list;
325  long i;
326 
327  new_list = gwlist_create();
328  lock(list);
329  i = 0;
330  while (i < list->len) {
331  if (cmp(GET(list, i), pat)) {
332  gwlist_append(new_list, GET(list, i));
333  delete_items_from_list(list, i, 1);
334  } else
335  ++i;
336  }
337  unlock(list);
338 
339  if (gwlist_len(new_list) == 0) {
340  gwlist_destroy(new_list, NULL);
341  return NULL;
342  }
343  return new_list;
344 }
static void lock(List *list)
Definition: list.c:593
void gwlist_append(List *list, void *item)
Definition: list.c:179
long gwlist_len(List *list)
Definition: list.c:166
static void unlock(List *list)
Definition: list.c:599
static void delete_items_from_list(List *list, long pos, long count)
Definition: list.c:693
#define gwlist_create()
Definition: list.h:136
Definition: list.c:102
#define GET(list, i)
Definition: list.c:116
void gwlist_destroy(List *list, gwlist_item_destructor_t *destructor)
Definition: list.c:145

◆ gwlist_get()

void* gwlist_get ( List list,
long  pos 
)

Definition at line 292 of file list.c.

References GET, gw_assert(), lock(), and unlock().

Referenced by abort_delivery(), abort_methods(), abort_pushes(), boxc_incoming_wdp_queue(), boxc_status(), build_request(), build_response(), catenate_msg(), cfg_get_multi_group(), check_do_elements(), check_login(), client_thread(), concat_handling_clear_old_parts(), concat_msgids(), create_onetrans(), deliver_pending_pushes(), dict_duplicate(), dict_keys(), dict_remove(), dict_traverse(), dict_traverse_sorted(), disconnect_other_sessions(), dlr_mem_flush(), dlr_mem_get(), dlr_mem_remove(), do_dump(), dump_tpis(), expire_cookies(), find_default_translation(), find_receiver_box(), find_translation(), get_cookies(), get_matching_translations(), get_pattern(), get_qvalue(), handle_submit(), have_cookie(), http_append_headers(), http_cgi_variable(), http_cgivar_dump(), http_cgivar_dump_into(), http_header_dump(), http_header_duplicate(), http_header_find_all(), http_header_find_first_real(), http_header_get(), http_header_pack(), http_header_remove_all(), http_header_split_auth_value(), http_header_value(), http_send_reply(), http_something_accepted(), http_use_proxy(), init_reroute(), init_smsbox_routes(), init_smsc_routes(), is_allowed_in_group(), is_single_group(), main(), main_for_extract(), main_for_list_add_and_delete(), main_for_producer_and_consumer(), mime_decompile(), mime_entity_dump_real(), mime_entity_duplicate(), mime_entity_get_part(), mime_entity_remove_part(), mime_entity_replace_part(), mime_entity_to_octstr(), mime_multipart_start_elem(), pack_challenge(), pack_tpis(), parse_attr_value(), parse_request_line(), prefix_allowed(), proxy_used_for_host(), randomize(), read_mime_headers(), read_some_headers(), refuse_unreplied_capabilities(), release_holding_methods(), remove_session_data(), response(), route_incoming_to_boxc(), route_incoming_to_smsc(), route_msg(), sanitize_capabilities(), set_cookies(), sms_split(), sms_to_smsboxes(), smsbox_req_handle(), smsc2_add_smsc(), smsc2_cleanup(), smsc2_find(), smsc2_graceful_restart(), smsc2_remove_smsc(), smsc2_restart_smsc(), smsc2_resume(), smsc2_rout(), smsc2_shutdown(), smsc2_start(), smsc2_status(), smsc2_stop_smsc(), smsc2_suspend(), smscconn_send(), soap_client_have_response(), soap_client_init_query(), soap_create_map(), soap_fetch_xml_data(), soap_get_index(), soap_map_xml_data(), soap_release_dependences(), store_file_for_each_message(), string_table_add(), string_table_apply(), string_table_sort_list(), strip_default_capabilities(), test_header_combine(), udp_addwdp(), udp_outgoing_queue(), udpc_find_mapping(), unpack_ack(), urltrans_fill_escape_codes(), urltrans_find_service(), urltrans_find_username(), user_find_by_username(), wap_map_destroy(), wap_map_url(), wap_push_ppg_pushuser_search_ip_from_wildcarded_list(), wdp_to_wapboxes(), wildcarded_ip_found(), wrapper_sender(), wsp_cap_dump_list(), wsp_cap_duplicate_list(), wsp_cap_get_data(), wsp_cap_pack_list(), wsp_headers_unpack(), wsp_pack_parameters(), xmlrpc_call_print(), xmlrpc_get_element(), xmlrpc_get_param(), and xmlrpc_print_array().

293 {
294  void *item;
295 
296  lock(list);
297  gw_assert(pos >= 0);
298  gw_assert(pos < list->len);
299  item = GET(list, pos);
300  unlock(list);
301  return item;
302 }
static void lock(List *list)
Definition: list.c:593
gw_assert(wtls_machine->packet_to_send !=NULL)
static void unlock(List *list)
Definition: list.c:599
#define GET(list, i)
Definition: list.c:116

◆ gwlist_insert()

void gwlist_insert ( List list,
long  pos,
void *  item 
)

Definition at line 214 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().

215 {
216  long i;
217 
218  lock(list);
219  gw_assert(pos >= 0);
220  gw_assert(pos <= list->len);
221 
222  make_bigger(list, 1);
223  for (i = list->len; i > pos; --i)
224  list->tab[INDEX(list, i)] = GET(list, i - 1);
225  list->tab[INDEX(list, pos)] = item;
226  ++list->len;
227  pthread_cond_signal(&list->nonempty);
228  unlock(list);
229 }
static void lock(List *list)
Definition: list.c:593
gw_assert(wtls_machine->packet_to_send !=NULL)
long len
Definition: list.c:107
static void unlock(List *list)
Definition: list.c:599
pthread_cond_t nonempty
Definition: list.c:110
void ** tab
Definition: list.c:104
static void make_bigger(List *list, long items)
Definition: list.c:612
#define INDEX(list, i)
Definition: list.c:115
#define GET(list, i)
Definition: list.c:116

◆ gwlist_len()

long gwlist_len ( List list)

Definition at line 166 of file list.c.

References List::len, lock(), and unlock().

Referenced by abort_delivery(), abort_methods(), abort_pushes(), at2_device_thread(), at2_read_modems(), at2_read_pending_incoming_messages(), at2_read_sms_memory(), bb_print_status(), boxc_incoming_wdp_queue(), boxc_status(), brunet_parse_body(), build_request(), build_response(), cfg_get_multi_group(), cgw_queued_cb(), cgw_sender(), check_application_headers(), check_do_elements(), check_login(), check_multipart(), check_num_args(), cimd2_destroy(), cimd2_queued_cb(), cimd2_receive_msg(), clickatell_parse_body(), client_destroy(), client_thread(), concat_msgids(), content_transformable(), create_onetrans(), decode_bearer_indication(), deliver_pending_pushes(), destroy_methodmachines(), destroy_pushmachines(), dict_duplicate(), dict_keys(), dict_remove(), dict_traverse(), dict_traverse_sorted(), disconnect_other_sessions(), dispatch_datagram(), dlr_mem_flush(), dlr_mem_get(), dlr_mem_messages(), dlr_mem_remove(), do_dump(), dump_tpis(), empty_msg_lists(), expire_cookies(), fdset_destroy(), find_default_translation(), find_receiver_box(), find_translation(), get_cookies(), get_matching_translations(), get_pattern(), get_qvalue(), get_x_kannel_from_headers(), gwlist_destroy(), gwlist_extract_matching(), gwlist_search_all(), handle_submit(), have_cookie(), heartbeat_stop(), http_append_headers(), http_cgi_variable(), http_cgivar_dump(), http_cgivar_dump_into(), http_header_combine(), http_header_dump(), http_header_duplicate(), http_header_find_all(), http_header_find_first_real(), http_header_pack(), http_header_remove_all(), http_header_split_auth_value(), http_header_value(), http_queue_thread(), http_send_reply(), http_something_accepted(), http_use_proxy(), httpsmsc_queued(), indicate_push_connection(), indicate_push_resume(), init_batch(), init_reroute(), init_smsbox_routes(), init_smsc_routes(), is_allowed_in_group(), is_single_group(), main(), main_for_extract(), main_for_list_add_and_delete(), main_for_producer_and_consumer(), mime_decompile(), mime_entity_dump_real(), mime_entity_duplicate(), mime_entity_get_part(), mime_entity_num_parts(), mime_entity_remove_part(), mime_entity_replace_part(), mime_entity_to_octstr(), mime_multipart_start_elem(), msg_to_pdu(), oisd_destroy(), oisd_queued_cb(), oisd_receive_msg(), pack_appid_list(), pack_challenge(), pack_tpis(), parse_attr_value(), parse_context_destroy(), parse_methodresponse_element(), parse_pop_limit(), parse_request_line(), prefix_allowed(), proxy_used_for_host(), queued_cb(), randomize(), read_mime_headers(), read_some_headers(), refuse_unreplied_capabilities(), release_holding_methods(), remove_pushless_session(), remove_session_data(), response(), route_incoming_to_boxc(), route_incoming_to_smsc(), route_msg(), run_batch(), run_smsbox(), run_wapbox(), sanitize_capabilities(), semaphore_getvalue(), send_message(), server_thread(), set_cookies(), sms_router(), sms_to_smsboxes(), smsbox_req_handle(), smsbox_sendota_post(), smsc2_add_smsc(), smsc2_cleanup(), smsc2_find(), smsc2_graceful_restart(), smsc2_restart_smsc(), smsc2_resume(), smsc2_rout(), smsc2_shutdown(), smsc2_start(), smsc2_status(), smsc2_suspend(), smsc_soap_create(), smscconn_send(), soap_add_msg_cb(), soap_client_have_response(), soap_client_init_query(), soap_create_map(), soap_fetch_xml_data(), soap_get_index(), soap_listener(), soap_map_xml_data(), soap_parse_mo(), soap_queued_cb(), soap_read_response(), soap_release_dependences(), sql_list(), store_file_for_each_message(), string_table_add(), string_table_add_many(), string_table_apply(), string_table_build(), string_table_collect_words(), string_table_sort_list(), strip_default_capabilities(), test_header_combine(), udp_addwdp(), udp_outgoing_queue(), udp_start(), udpc_destroy(), udpc_find_mapping(), unpack_ack(), urltrans_fill_escape_codes(), urltrans_find_username(), user_find_by_username(), wap_appl_get_load(), wap_dispatch_datagram(), wap_map_destroy(), wap_map_url(), wap_push_ppg_pushuser_search_ip_from_wildcarded_list(), wap_push_ppg_shutdown(), wdp_to_wapboxes(), wildcarded_ip_found(), wrapper_queued(), wrapper_sender(), write_request_thread(), wsp_cap_dump_list(), wsp_cap_duplicate_list(), wsp_cap_get_data(), wsp_cap_pack_list(), wsp_headers_pack(), wsp_headers_unpack(), wsp_pack_parameters(), wsp_push_client_shutdown(), wsp_session_shutdown(), wtp_event_dump(), wtp_initiator_shutdown(), wtp_pdu_destroy(), wtp_resp_shutdown(), wtp_tid_cache_shutdown(), xmlrpc_call_print(), xmlrpc_count_elements(), xmlrpc_count_params(), xmlrpc_get_param(), and xmlrpc_print_array().

167 {
168  long len;
169 
170  if (list == NULL)
171  return 0;
172  lock(list);
173  len = list->len;
174  unlock(list);
175  return len;
176 }
static void lock(List *list)
Definition: list.c:593
long len
Definition: list.c:107
static void unlock(List *list)
Definition: list.c:599

◆ gwlist_lock()

◆ gwlist_produce()

◆ gwlist_producer_count()

int gwlist_producer_count ( List list)

Definition at line 391 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().

392 {
393  int ret;
394  lock(list);
395  ret = list->num_producers;
396  unlock(list);
397  return ret;
398 }
static void lock(List *list)
Definition: list.c:593
static void unlock(List *list)
Definition: list.c:599
long num_producers
Definition: list.c:111

◆ gwlist_remove_producer()

void gwlist_remove_producer ( List list)

Definition at line 401 of file list.c.

References gw_assert(), lock(), List::nonempty, List::num_producers, and unlock().

Referenced by alog(), bb_isolate(), bb_resume(), bb_smscconn_killed(), boxc_sender(), cimd2_shutdown_cb(), cimd2_start_cb(), client_shutdown(), eq_remove_producer(), gw_rwlock_unlock(), gw_timer_destroy(), gw_timer_elapsed_destroy(), gw_timer_elapsed_destroy_cb(), gwtimer_destroy(), http_caller_signal_shutdown(), httpsmsc_shutdown(), main(), oisd_shutdown_cb(), oisd_start_cb(), port_remove(), producer(), run_smsbox(), run_wapbox(), server_shutdown(), service_router(), set_shutdown_status(), sms_router(), sms_to_smsboxes(), smsboxc_run(), smsc2_add_smsc(), smsc2_graceful_restart(), smsc2_remove_smsc(), smsc2_shutdown(), smsc2_start(), sql_list(), store_file_load(), store_spool_load(), udp_die(), udp_receiver(), udp_sender(), udp_shutdown(), wap_appl_shutdown(), wap_push_ota_shutdown(), wap_push_ppg_shutdown(), wapboxc_run(), wdp_router(), wdp_to_wapboxes(), wrapper_sender(), wrapper_shutdown(), wrapper_start(), wsp_push_client_shutdown(), wsp_session_shutdown(), wsp_unit_shutdown(), wtp_initiator_shutdown(), and wtp_resp_shutdown().

402 {
403  lock(list);
404  gw_assert(list->num_producers > 0);
405  --list->num_producers;
406  pthread_cond_broadcast(&list->nonempty);
407  unlock(list);
408 }
static void lock(List *list)
Definition: list.c:593
gw_assert(wtls_machine->packet_to_send !=NULL)
static void unlock(List *list)
Definition: list.c:599
pthread_cond_t nonempty
Definition: list.c:110
long num_producers
Definition: list.c:111

◆ gwlist_search()

void* gwlist_search ( List list,
void *  pattern,
int(*)(void *, void *)  cmp 
)

Definition at line 486 of file list.c.

References GET, List::len, lock(), and unlock().

Referenced by add_sar_transaction(), assembly_sar_event(), at2_detect_modem_type(), at2_init_device(), cfg_get_group_checksum(), cfg_read(), check_allowed_translation(), client_is_persistent(), dict_get(), dict_put(), dict_put_true(), find_method_machine(), find_ppg_push_machine_using_pi_push_id(), find_ppg_push_machine_using_pid(), find_push_machine(), find_session_machine(), find_session_machine_by_id(), find_unit_ppg_push_machine_using_pi_push_id(), init_machine_find(), parse_attribute(), port_remove(), push_client_machine_find_using_transid(), resp_machine_find(), route_msg(), session_find_using_pi_client_address(), smscconn_usable(), tid_cached(), wap_push_ppg_have_push_session_for(), and wap_push_ppg_have_push_session_for_sid().

487 {
488  void *item;
489  long i;
490 
491  lock(list);
492  item = NULL;
493  for (i = 0; i < list->len; ++i) {
494  item = GET(list, i);
495  if (cmp(item, pattern)) {
496  break;
497  }
498  }
499  if (i == list->len) {
500  item = NULL;
501  }
502  unlock(list);
503 
504  return item;
505 }
static void lock(List *list)
Definition: list.c:593
long len
Definition: list.c:107
static void unlock(List *list)
Definition: list.c:599
#define GET(list, i)
Definition: list.c:116

◆ gwlist_search_all()

List* gwlist_search_all ( List list,
void *  pattern,
int(*)(void *, void *)  cmp 
)

Definition at line 508 of file list.c.

References GET, gwlist_append(), gwlist_create, gwlist_destroy(), gwlist_len(), List::len, lock(), and unlock().

Referenced by disconnect_other_sessions(), port_remove(), release_holding_methods(), and smsc2_graceful_restart().

509 {
510  List *new_list;
511  void *item;
512  long i;
513 
514  new_list = gwlist_create();
515 
516  lock(list);
517  item = NULL;
518  for (i = 0; i < list->len; ++i) {
519  item = GET(list, i);
520  if (cmp(item, pattern))
521  gwlist_append(new_list, item);
522  }
523  unlock(list);
524 
525  if (gwlist_len(new_list) == 0) {
526  gwlist_destroy(new_list, NULL);
527  new_list = NULL;
528  }
529 
530  return new_list;
531 }
static void lock(List *list)
Definition: list.c:593
void gwlist_append(List *list, void *item)
Definition: list.c:179
long gwlist_len(List *list)
Definition: list.c:166
long len
Definition: list.c:107
static void unlock(List *list)
Definition: list.c:599
#define gwlist_create()
Definition: list.h:136
Definition: list.c:102
#define GET(list, i)
Definition: list.c:116
void gwlist_destroy(List *list, gwlist_item_destructor_t *destructor)
Definition: list.c:145

◆ gwlist_search_equal()

long gwlist_search_equal ( List list,
void *  item 
)

Definition at line 534 of file list.c.

References GET, List::len, lock(), and unlock().

Referenced by smsc2_graceful_restart(), and smsc2_rout().

535 {
536  long i;
537  long ret = -1;
538 
539  lock(list);
540  for (i = 0; i < list->len; i++) {
541  if (GET(list, i) == item) {
542  ret = i;
543  break;
544  }
545  }
546  unlock(list);
547 
548  return ret;
549 }
static void lock(List *list)
Definition: list.c:593
long len
Definition: list.c:107
static void unlock(List *list)
Definition: list.c:599
#define GET(list, i)
Definition: list.c:116

◆ gwlist_sort()

void gwlist_sort ( List list,
int(*)(const void *, const void *)  cmp 
)

Definition at line 576 of file list.c.

References gw_assert(), List::len, lock(), quicksort(), and unlock().

Referenced by cfg_get_group_checksum(), dict_traverse_sorted(), and main().

577 {
578  gw_assert(list != NULL && cmp != NULL);
579 
580  lock(list);
581  if (list->len == 0) {
582  /* nothing to sort */
583  unlock(list);
584  return;
585  }
586  quicksort(list, 0, list->len - 1, cmp);
587  unlock(list);
588 }
static void lock(List *list)
Definition: list.c:593
gw_assert(wtls_machine->packet_to_send !=NULL)
static void quicksort(List *list, long left, long right, int(*cmp)(const void *, const void *))
Definition: list.c:552
long len
Definition: list.c:107
static void unlock(List *list)
Definition: list.c:599

◆ gwlist_timed_consume()

void* gwlist_timed_consume ( List list,
long  sec 
)

Definition at line 453 of file list.c.

References delete_items_from_list(), GET, gwthread_self(), List::len, lock(), Mutex::mutex, List::nonempty, List::num_consumers, List::num_producers, Mutex::owner, List::single_operation_lock, and unlock().

Referenced by sms_router().

454 {
455  void *item;
456  struct timespec abstime;
457  int rc;
458 
459  abstime.tv_sec = time(NULL) + sec;
460  abstime.tv_nsec = 0;
461 
462  lock(list);
463  ++list->num_consumers;
464  while (list->len == 0 && list->num_producers > 0) {
465  list->single_operation_lock->owner = -1;
466  pthread_cleanup_push((void(*)(void*))pthread_mutex_unlock, &list->single_operation_lock->mutex);
467  rc = pthread_cond_timedwait(&list->nonempty,
468  &list->single_operation_lock->mutex, &abstime);
469  pthread_cleanup_pop(0);
471  if (rc == ETIMEDOUT)
472  break;
473  }
474  if (list->len > 0) {
475  item = GET(list, 0);
476  delete_items_from_list(list, 0, 1);
477  } else {
478  item = NULL;
479  }
480  --list->num_consumers;
481  unlock(list);
482  return item;
483 }
long num_consumers
Definition: list.c:112
static void lock(List *list)
Definition: list.c:593
long len
Definition: list.c:107
static void unlock(List *list)
Definition: list.c:599
pthread_mutex_t mutex
Definition: thread.h:77
Mutex * single_operation_lock
Definition: list.c:108
static void delete_items_from_list(List *list, long pos, long count)
Definition: list.c:693
long gwthread_self(void)
pthread_cond_t nonempty
Definition: list.c:110
long num_producers
Definition: list.c:111
long owner
Definition: thread.h:78
#define GET(list, i)
Definition: list.c:116

◆ gwlist_unlock()

◆ gwlist_wait_until_nonempty()

int gwlist_wait_until_nonempty ( List list)

Definition at line 361 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().

362 {
363  int ret;
364 
365  lock(list);
366  while (list->len == 0 && list->num_producers > 0) {
367  list->single_operation_lock->owner = -1;
368  pthread_cleanup_push((void(*)(void*))pthread_mutex_unlock, &list->single_operation_lock->mutex);
369  pthread_cond_wait(&list->nonempty,
370  &list->single_operation_lock->mutex);
372  pthread_cleanup_pop(0);
373  }
374  if (list->len > 0)
375  ret = 1;
376  else
377  ret = -1;
378  unlock(list);
379  return ret;
380 }
static void lock(List *list)
Definition: list.c:593
long len
Definition: list.c:107
static void unlock(List *list)
Definition: list.c:599
pthread_mutex_t mutex
Definition: thread.h:77
Mutex * single_operation_lock
Definition: list.c:108
long gwthread_self(void)
pthread_cond_t nonempty
Definition: list.c:110
long num_producers
Definition: list.c:111
long owner
Definition: thread.h:78

◆ gwthread_self()

◆ lock()

◆ make_bigger()

static void make_bigger ( List list,
long  items 
)
static

Definition at line 612 of file list.c.

References gw_assert(), List::len, List::start, List::tab, and List::tab_size.

Referenced by gwlist_append(), gwlist_append_unique(), and gwlist_insert().

613 {
614  long old_size, new_size;
615  long len_at_beginning, len_at_end;
616 
617  if (list->len + items <= list->tab_size)
618  return;
619 
620  old_size = list->tab_size;
621  new_size = old_size + items;
622  list->tab = gw_realloc(list->tab, new_size * sizeof(void *));
623  list->tab_size = new_size;
624 
625  /*
626  * Now, one of the following situations is in effect
627  * (* is used, empty is unused element):
628  *
629  * Case 1: Used area did not wrap. No action is necessary.
630  *
631  * old_size new_size
632  * v v
633  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
634  * | |*|*|*|*|*|*| | | | | | | | | | | | | | | | |
635  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
636  * ^ ^
637  * start start+len
638  *
639  * Case 2: Used area wrapped, but the part at the beginning
640  * of the array fits into the new area. Action: move part
641  * from beginning to new area.
642  *
643  * old_size new_size
644  * v v
645  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
646  * |*|*| | | | | | | |*|*|*| | | | | | | | | | | |
647  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
648  * ^ ^
649  * start+len start
650  *
651  * Case 3: Used area wrapped, and the part at the beginning
652  * of the array does not fit into the new area. Action: move
653  * as much as will fit from beginning to new area and move
654  * the rest to the beginning.
655  *
656  * old_size new_size
657  * v v
658  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
659  * |*|*|*|*|*|*|*|*|*| | | | | | | | |*|*|*|*| | |
660  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
661  * ^ ^
662  * start+len start
663  */
664 
665  gw_assert(list->start < old_size ||
666  (list->start == 0 && old_size == 0));
667  if (list->start + list->len > old_size) {
668  len_at_end = old_size - list->start;
669  len_at_beginning = list->len - len_at_end;
670  if (len_at_beginning <= new_size - old_size) {
671  /* This is Case 2. */
672  memmove(list->tab + old_size,
673  list->tab,
674  len_at_beginning * sizeof(void *));
675  } else {
676  /* This is Case 3. */
677  memmove(list->tab + old_size,
678  list->tab,
679  (new_size - old_size) * sizeof(void *));
680  memmove(list->tab,
681  list->tab + (new_size - old_size),
682  (len_at_beginning - (new_size - old_size))
683  * sizeof(void *));
684  }
685  }
686 }
gw_assert(wtls_machine->packet_to_send !=NULL)
long len
Definition: list.c:107
long tab_size
Definition: list.c:105
long start
Definition: list.c:106
void ** tab
Definition: list.c:104

◆ quicksort()

static void quicksort ( List list,
long  left,
long  right,
int(*)(const void *, const void *)  cmp 
)
static

Definition at line 552 of file list.c.

References GET.

Referenced by gwlist_sort().

553 {
554  if (left < right) {
555  long l = left;
556  long r = right;
557  void *pivot = GET(list, right);
558 
559  do {
560  while (cmp(GET(list, l), pivot) < 0) l++;
561  while (cmp(GET(list, r), pivot) > 0) r--;
562  if (l <= r) {
563  void *swap = GET(list, l);
564  GET(list, l) = GET(list, r);
565  GET(list, r) = swap;
566  l++;
567  r--;
568  }
569  } while(l <= r);
570 
571  quicksort(list, left, r, cmp);
572  quicksort(list, l, right, cmp);
573  }
574 }
static void quicksort(List *list, long left, long right, int(*cmp)(const void *, const void *))
Definition: list.c:552
#define GET(list, i)
Definition: list.c:116

◆ unlock()

See file LICENSE for details about the license agreement for using, modifying, copying or deriving work from this software.