#ifndef extc_phase2_h_
#define extc_phase2_h_
/***************************************************************************
 *  phase2.h
 *
 *  Tue Jul 26 13:42:18 2005
 *  Copyright  2005  James Scully- aka jtox
 *  Email jtoxification @ the-only-free-2-gig-account-service-online
 ***************************************************************************
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Library General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
 */
 
 
/* Extended C Phase #2: The *this pointer. */
/* Jamie Scully - July 21st, 2005         */
/* in Phase #2, we are using somewhat of a layered
   approach, where we use object-orientedness since
   we know there will be only one object registry
   in a given program -- we just create a global
   *self pointer with static scope for our functions.
    For thoes of you who have need for only single objects
    such as this one, you may want to copy this design.
    
    And for those of you who /know/ what you are doing,
    There will be a mixed version of this design and the
    design specified in phase 1, to cut down on redundancy.
    
    Furthermore, once again, yes, I do know about C++'s 
    extern C {#include <INSERT NAME OF C HEADER>}
*/
#include "phase5.h"
#include "hash.h"

extern int  MUTEX__   (int*);
extern int   SemP__   (int*);
extern int   SemV__   (int*);

static int     find___ ();
static void*current___ (int pid,int tid);
static void*    pop___ (int pid,int tid); 
static void  remove___ (void* item     );
//static void  exists___ (void* item     );
static int     lock___ ();
static void  unlock___ ();
static void     add___ ();
static int    slock___ ();
static void unslock___ ();
static unsigned long long i2ull___(int pid,int tid);
/* The object registry ! */

typedef struct Registry
{
        int  (*    lock) ();
        void (*  unlock) ();
        int  (*   slock) ();
        void (* unslock) ();
        int  (*    find) ();
        void*(* current) ();
        void (*     add) ();
        void*(*     pop) ();
        void (*  remove) ();
    //  void (*  exists) ();

} Registry;

//Private /////////////////////////////.../////////////////////////////////////

/* 
    I made this version of the registry in a bit of a hurry. That's why its
    not a fully-optimized hash-array.  I'll swap it out later, but for
    now, it works, and well!

    BEFORE YOU ASK: 

      Yes, the hash code sucks.  Yes there is an interface to this if you
      want to make your own backend rather than the hash table.
      Yes I know about C++'s extern C {#include <name of c header>}
    
*/
    static int registry_mutex;
    static int this_mutex;

    static Registry registry__[1] = 
    {
        (Registry)
        {
               lock___,
             unlock___,
              slock___,
            unslock___,
               find___,
            current___,
                add___,
                pop___,
             remove___
        } 
    };

//Functions /////////////////////////////...//////////////////////////////////
    
    static int     lock___() {SemP__(&registry_mutex);return 0;}
    static void  unlock___() {SemV__(&registry_mutex);         }
    
    static int    slock___() {SemP__(&this_mutex    );return 0;}
    static void unslock___() {SemV__(&this_mutex    );         }
    
    static int find___()
    {
        void* v = obj_db->search();
        unlock___();
        
        unsigned long long ull = i2ull___(GETPID(),GETTID());
        
        slock___();
            self_db->add(v,ull);
        unslock___();
        
        return 0;
    }

    static unsigned long long i2ull___(int pid,int tid)
    {
        union llii___{ int i[2];unsigned long long ll; } il[1];
        il->i[0]=pid;
        il->i[1]=tid;
        return   il->ll;
    }

    /*warning: wrap calls to this around registry__->slock()/->unslock();*/
    static void* current___(int pid,int tid)
    {
        return self_db->search(i2ull___(pid,tid));
    }

    static void* pop___(int pid,int tid)
    {
        slock___();
            return self_db->remove(i2ull___(pid,tid));
        unslock___();
    }

    static void remove___(void* item)
    {
        lock___();
            obj_db->remove(item);
        unlock___();
    }
    
    static void add___(void* item)
    {
        static int started;
        
      /* This style below serves no real purpose, except to remind 
         you that you'll soon need a way to prevent this code from 
         occurring multiple times (race condition)
         Change it later.
            The array-of-multiple-functionpointers whose functions modify
         the array index wouldn't work because it's actually more work
         to call the function and dereference the pointer and array than
         to simply use an if-statement: only use self-modifying functionpointer
         arrays when you're calling other functions, NOT when you're using
         conditional expressions.
        */
        
        if (!started && ++started)
        {
            MUTEX__(&this_mutex    );
            MUTEX__(&registry_mutex);
            initialize_database();
        }
        
        lock___();      
        
            obj_db->add(item);
                
        unlock___();
    }

    

#endif