Skip to content
Snippets Groups Projects
Select Git revision
  • c43e8cadd02224b249156fd2ff3e44e8f71c7b88
  • master default protected
  • 9.0
  • marcus/wix3
  • 8.0
  • nt-tools
  • 7.8
  • 7.6
  • 7.4
  • 7.2
  • 7.0
  • 0.6
  • rosuav/latex-markdown-renderer
  • rxnpatch/rxnpatch
  • marcus/gobject-introspection
  • rxnpatch/8.0
  • rosuav/pre-listening-ports
  • rosuav/async-annotations
  • rosuav/pgsql-ssl
  • rxnpatch/rxnpatch-broken/2023-10-06T094250
  • grubba/fdlib
  • v8.0.2020
  • v8.0.2018
  • v8.0.2016
  • v8.0.2014
  • v8.0.2012
  • v8.0.2008
  • v8.0.2006
  • v8.0.2004
  • v8.0.2002
  • v8.0.2000
  • v8.0.1998
  • v8.0.1996
  • v8.0.1994
  • v8.0.1992
  • v8.0.1990
  • v8.0.1988
  • v8.0.1986
  • rxnpatch/clusters/8.0/2025-04-29T124414
  • rxnpatch/2025-04-29T124414
  • v8.0.1984
41 results

callback.c

Blame
  • user avatar
    Per Hedbor authored
    It mainly confuses things when you are searching for code.
    
    I also removed a few instances of 'well, this would be nice, but is
    not possible' and 'this code is obviously broken because X' etc.
    
    We do, after all, have a revision control system. With history. :)
    bbbe95e7
    History
    callback.c 3.40 KiB
    /*
    || This file is part of Pike. For copyright information see COPYRIGHT.
    || Pike is distributed under GPL, LGPL and MPL. See the file COPYING
    || for more information.
    */
    
    #include "global.h"
    #include "pike_macros.h"
    #include "callback.h"
    #include "pike_error.h"
    #include "block_allocator.h"
    
    struct callback_list fork_child_callback;
    
    /*
     * This file is used to simplify the management of callbacks when certain
     * events occur. The callbacks are managed as linked lists, allocated in
     * chunks.
     */
    
    /* FIXME: free all chunks of memory at exit */
    
    struct callback
    {
      struct callback *next;
      callback_func call;
      callback_func free_func;
      void *arg;
    };
    
    #define CALLBACK_CHUNK 128
    
    static struct block_allocator callback_allocator
        = BA_INIT(sizeof(struct callback), CALLBACK_CHUNK);
    
    void count_memory_in_callbacks(size_t * num, size_t * size) {
        ba_count_all(&callback_allocator, num, size);
    }
    
    
    #ifdef PIKE_DEBUG
    extern int d_flag;
    
    static void check_callback_chain(struct callback_list *lst)
    {
      int len=0;
      struct callback *foo;
      if(d_flag>4)
      {
        for(foo=lst->callbacks;foo;foo=foo->next)
        {
          if((len & 1024)==1023)
          {
    	int len2=0;
    	struct callback *tmp;
    	for(tmp=foo->next;tmp && len2<=len;tmp=tmp->next)
    	{
    #ifdef PIKE_DEBUG
    	  if(tmp==foo)
    	    Pike_fatal("Callback list is cyclic!!!\n");
    #endif
    	}
          }
          len++;
        }
      }
    }
    #else
    #define check_callback_chain(X)
    #endif
    
    /* Return the first free callback struct, allocate more if needed */
    
    
    /* Traverse a linked list of callbacks and call all the active callbacks
     * in the list. Deactivated callbacks are freed and placed in the free list.
     */
    PMOD_EXPORT void low_call_callback(struct callback_list *lst, void *arg)
    {
      int this_call;
      struct callback *l,**ptr;
    
      lst->num_calls++;
      this_call=lst->num_calls;
    
      check_callback_chain(lst);
      ptr=&lst->callbacks;
      while((l=*ptr))
      {
        if(l->call)
        {
          l->call(l,l->arg, arg);
          if(lst->num_calls != this_call) return;
        }
    
        if(!l->call)
        {
          if(l->free_func)
    	l->free_func(l, l->arg, 0);
    
          while(*ptr != l)
          {
    	ptr=&(ptr[0]->next);
    #ifdef PIKE_DEBUG
    	if(!*ptr)
    	{
    	  /* We totally failed to find where we are in the linked list.. */
    	  Pike_fatal("Callback linked list breakdown.\n");
    	}
    #endif
          }
    
          *ptr=l->next;
          ba_free(&callback_allocator, l);
        }else{
          ptr=& l->next;
        }
        check_callback_chain(lst);
      }
    }
    
    /* Add a callback to the linked list pointed to by ptr. */
    PMOD_EXPORT struct callback *debug_add_to_callback(struct callback_list *lst,
    				       callback_func call,
    				       void *arg,
    				       callback_func free_func)
    {
      struct callback *l;
      l=ba_alloc(&callback_allocator);
      l->call=call;
      l->arg=arg;
      l->free_func=free_func;
    
      l->next=lst->callbacks;
      lst->callbacks=l;
    
      check_callback_chain(lst);
    
      return l;
    }
    
    /* This function deactivates a callback.
     * It is not actually freed until next time this callback is "called"
     */
    PMOD_EXPORT void *remove_callback(struct callback *l)
    {
      l->call=0;
      l->free_func=0;
      return l->arg;
    }
    
    /* Free all the callbacks in a linked list of callbacks */
    void free_callback_list(struct callback_list *lst)
    {
      struct callback *l,**ptr;
      check_callback_chain(lst);
      ptr=& lst->callbacks;
      while((l=*ptr))
      {
        if(l->free_func)
          l->free_func(l, l->arg, 0);
        *ptr=l->next;
        ba_free(&callback_allocator, l);
      }
    }
    
    void cleanup_callbacks(void)
    {
      ba_destroy(&callback_allocator);
    }