Release 980822
[wine] / server / object.c
1 /*
2  * Server-side objects
3  * These are the server equivalent of K32OBJ
4  *
5  * Copyright (C) 1998 Alexandre Julliard
6  */
7
8 #include <assert.h>
9 #include <limits.h>
10 #include <stdlib.h>
11 #include <string.h>
12
13 #include "server.h"
14
15 #include "server/object.h"
16
17 int debug_level = 0;
18
19 struct object_name
20 {
21     struct object_name *next;
22     struct object      *obj;
23     int                 len;
24     char                name[1];
25 };
26
27 #define NAME_HASH_SIZE 37
28
29 static struct object_name *names[NAME_HASH_SIZE];
30
31 /*****************************************************************/
32
33 static int get_name_hash( const char *name )
34 {
35     int hash = 0;
36     while (*name) hash ^= *name++;
37     return hash % NAME_HASH_SIZE;
38 }
39
40 static struct object_name *add_name( struct object *obj, const char *name )
41 {
42     struct object_name *ptr;
43     int hash = get_name_hash( name );
44     int len = strlen( name );
45
46     if (!(ptr = (struct object_name *)malloc( sizeof(*ptr) + len )))
47         return NULL;
48     ptr->next = names[hash];
49     ptr->obj  = obj;
50     ptr->len  = len;
51     strcpy( ptr->name, name );
52     names[hash] = ptr;
53     return ptr;
54 }
55
56 static void free_name( struct object *obj )
57 {
58     int hash = get_name_hash( obj->name->name );
59     struct object_name **pptr = &names[hash];
60     while (*pptr && *pptr != obj->name) pptr = &(*pptr)->next;
61     assert( *pptr );
62     *pptr = (*pptr)->next;
63     free( obj->name );
64 }
65
66 /* initialize an already allocated object */
67 void init_object( struct object *obj, const struct object_ops *ops,
68                   const char *name )
69 {
70     obj->refcount = 1;
71     obj->ops      = ops;
72     obj->head     = NULL;
73     obj->tail     = NULL;
74     if (!name) obj->name = NULL;
75     else obj->name = add_name( obj, name );
76 }
77
78 /* grab an object (i.e. increment its refcount) and return the object */
79 struct object *grab_object( void *ptr )
80 {
81     struct object *obj = (struct object *)ptr;
82     assert( obj->refcount < INT_MAX );
83     obj->refcount++;
84     return obj;
85 }
86
87 /* release an object (i.e. decrement its refcount) */
88 void release_object( void *ptr )
89 {
90     struct object *obj = (struct object *)ptr;
91     assert( obj->refcount );
92     if (!--obj->refcount)
93     {
94         /* if the refcount is 0, nobody can be in the wait queue */
95         assert( !obj->head );
96         assert( !obj->tail );
97         if (obj->name) free_name( obj );
98         obj->ops->destroy( obj );
99     }
100 }
101
102 /* find an object by its name; the refcount is incremented */
103 struct object *find_object( const char *name )
104 {
105     int hash = get_name_hash( name );
106     struct object_name *ptr = names[hash];
107     while (ptr && strcmp( ptr->name, name )) ptr = ptr->next;
108     if (!ptr) return NULL;
109     grab_object( ptr->obj );
110     return ptr->obj;
111 }