/* * SDL_sound -- An abstract sound format decoding API. * Copyright (C) 2001 Ryan C. Gordon. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* * Some extra RWops that are needed or are just handy to have. * * Please see the file LICENSE.txt in the source's root directory. * * This file written by Ryan C. Gordon. (icculus@icculus.org) */ #include #include #include "SDL.h" /* * The Reference Counter RWops... */ typedef struct { SDL_RWops *rw; /* The actual RWops we're refcounting... */ int refcount; /* The refcount; starts at 1. If goes to 0, delete. */ } RWRefCounterData; /* Just pass through to the actual SDL_RWops's method... */ static int refcounter_seek(SDL_RWops *rw, int offset, int whence) { RWRefCounterData *data = (RWRefCounterData *) rw->hidden.unknown.data1; return(data->rw->seek(data->rw, offset, whence)); } /* refcounter_seek */ /* Just pass through to the actual SDL_RWops's method... */ static int refcounter_read(SDL_RWops *rw, void *ptr, int size, int maxnum) { RWRefCounterData *data = (RWRefCounterData *) rw->hidden.unknown.data1; return(data->rw->read(data->rw, ptr, size, maxnum)); } /* refcounter_read */ /* Just pass through to the actual SDL_RWops's method... */ static int refcounter_write(SDL_RWops *rw, const void *ptr, int size, int num) { RWRefCounterData *data = (RWRefCounterData *) rw->hidden.unknown.data1; return(data->rw->write(data->rw, ptr, size, num)); } /* refcounter_write */ /* * Decrement the reference count. If there are no more references, pass * through to the actual SDL_RWops's method, and then clean ourselves up. */ static int refcounter_close(SDL_RWops *rw) { int retval = 0; RWRefCounterData *data = (RWRefCounterData *) rw->hidden.unknown.data1; data->refcount--; if (data->refcount <= 0) { retval = data->rw->close(data->rw); free(data); SDL_FreeRW(rw); } /* if */ return(retval); } /* refcounter_close */ void RWops_RWRefCounter_addRef(SDL_RWops *rw) { RWRefCounterData *data = (RWRefCounterData *) rw->hidden.unknown.data1; data->refcount++; } /* RWops_RWRefCounter_addRef */ SDL_RWops *RWops_RWRefCounter_new(SDL_RWops *rw) { SDL_RWops *retval = NULL; if (rw == NULL) { SDL_SetError("NULL argument to RWops_RWRefCounter_new()."); return(NULL); } /* if */ retval = SDL_AllocRW(); if (retval != NULL) { RWRefCounterData *data; data = (RWRefCounterData *) malloc(sizeof (RWRefCounterData)); if (data == NULL) { SDL_SetError("Out of memory."); SDL_FreeRW(retval); retval = NULL; } /* if */ else { data->rw = rw; data->refcount = 1; retval->hidden.unknown.data1 = data; retval->seek = refcounter_seek; retval->read = refcounter_read; retval->write = refcounter_write; retval->close = refcounter_close; } /* else */ } /* if */ return(retval); } /* RWops_RWRefCounter_new */ /* * RWops pooling... */ static SDL_RWops *rwops_pool = NULL; static SDL_mutex *rwops_pool_mutex = NULL; SDL_RWops *RWops_pooled_alloc(void) { SDL_RWops *rw; if (rwops_pool_mutex == NULL) return(NULL); /* never initialized. */ SDL_LockMutex(rwops_pool_mutex); rw = rwops_pool; if (rw) rwops_pool = (SDL_RWops *) (rw->hidden.unknown.data1); SDL_UnlockMutex(rwops_pool_mutex); if (!rw) rw = (SDL_RWops *) malloc(sizeof (SDL_RWops)); return(rw); } /* RWops_pooled_alloc */ void RWops_pooled_free(SDL_RWops *rw) { if (rwops_pool_mutex == NULL) return; /* never initialized...why are we here? */ if (rw == NULL) return; SDL_LockMutex(rwops_pool_mutex); rw->hidden.unknown.data1 = rwops_pool; rwops_pool = rw; SDL_UnlockMutex(rwops_pool_mutex); } /* RWops_pooled_free */ int RWops_pooled_init(void) { const int preallocate = 50; int i; rwops_pool_mutex = SDL_CreateMutex(); if (rwops_pool_mutex == NULL) return(0); for (i = 0; i < preallocate; i++) RWops_pooled_free(RWops_pooled_alloc()); return(1); } /* RWops_pooled_init */ void RWops_pooled_deinit(void) { SDL_RWops *cur; SDL_RWops *next; if (rwops_pool_mutex == NULL) return; /* never initialized. */ SDL_LockMutex(rwops_pool_mutex); /* all allocated rwops must be in the pool now, or the memory leaks. */ cur = rwops_pool; rwops_pool = NULL; SDL_UnlockMutex(rwops_pool_mutex); SDL_DestroyMutex(rwops_pool_mutex); rwops_pool_mutex = NULL; while (cur) { next = (SDL_RWops *) (cur->hidden.unknown.data1); free(cur); cur = next; } /* while */ } /* RWops_pooled_deinit */ /* end of extra_rwops.c ... */