/* httperf -- a tool for measuring web server performance Copyright (C) 2000 Hewlett-Packard Company Contributed by David Mosberger-Tang This file is part of httperf, a web server performance measurment tool. 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 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 */ #include #include #include #include #include #include #include #include #include #include #include #define ALIGN(s) (((s) + sizeof (double) - 1) & ~(sizeof (double) - 1)) static size_t type_size[OBJ_NUM_TYPES] = { ALIGN (sizeof (Conn)), ALIGN (sizeof (Call)), ALIGN (sizeof (Sess)) }; struct free_list_el { struct free_list_el *next; }; static struct free_list_el *free_list[OBJ_NUM_TYPES]; static void object_destroy (Object *obj) { Object_Type type = obj->type; struct free_list_el *el; Event_Type event = 0; Any_Type arg; switch (type) { case OBJ_CALL: call_deinit ((Call *) obj); event = EV_CALL_DESTROYED; break; case OBJ_CONN: conn_deinit ((Conn *) obj); event = EV_CONN_DESTROYED; break; case OBJ_SESS: sess_deinit ((Sess *) obj); event = EV_SESS_DESTROYED; break; default: assert (0); break; } arg.l = 0; event_signal (event, obj, arg); /* Each object must be at least the size and alignment of "struct free_list_el". Malloc takes care of returning properly aligned objects. */ el = (struct free_list_el *) obj; el->next = free_list[type]; free_list[type] = el; } size_t object_expand (Object_Type type, size_t size) { size_t offset = type_size[type]; type_size[type] += ALIGN (size); return offset; } Object * object_new (Object_Type type) { struct free_list_el *el; Event_Type event = 0; size_t obj_size; Any_Type arg; Object *obj; obj_size = type_size[type]; if (free_list[type]) { el = free_list[type]; free_list[type] = el->next; obj = (Object *) el; } else { obj = malloc (obj_size); if (!obj) { fprintf (stderr, "%s.object_new: %s\n", prog_name, strerror (errno)); return 0; } } memset (obj, 0, obj_size); obj->ref_count = 1; obj->type = type; switch (type) { case OBJ_CALL: call_init ((Call *) obj); event = EV_CALL_NEW; break; case OBJ_CONN: conn_init ((Conn *) obj); event = EV_CONN_NEW; break; case OBJ_SESS: sess_init ((Sess *) obj); event = EV_SESS_NEW; break; default: panic ("object_new: bad object type %d\n", type); break; } arg.l = 0; event_signal (event, obj, arg); return obj; } void object_dec_ref (Object *obj) { assert (obj->ref_count > 0); if (--obj->ref_count == 0) object_destroy (obj); }