📄 misc.h
字号:
// Copyright (C) 1999-2005 Open Source Telecom Corporation.//// 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.// // As a special exception, you may use this file as part of a free software// library without restriction. Specifically, if other files instantiate// templates or use macros or inline functions from this file, or you compile// this file and link it with other files to produce an executable, this// file does not by itself cause the resulting executable to be covered by// the GNU General Public License. This exception does not however // invalidate any other reasons why the executable file might be covered by// the GNU General Public License. //// This exception applies only to the code released under the name GNU// Common C++. If you copy code from other releases into a copy of GNU// Common C++, as the General Public License permits, the exception does// not apply to the code that you add in this way. To avoid misleading// anyone as to the status of such modified files, you must delete// this exception notice from them.//// If you write modifications of your own for GNU Common C++, it is your choice// whether to permit this exception to apply to your modifications.// If you do not wish that, delete this exception notice.///** * @file misc.h * @short Memory management, configuration keydata objects and string * tokenizer. **/#ifndef CCXX_MISC_H_#define CCXX_MISC_H_#ifndef CCXX_MISSING_H_#include <cc++/missing.h>#endif#ifndef CCXX_THREAD_H_#include <cc++/thread.h>#endif#define KEYDATA_INDEX_SIZE 97#define KEYDATA_PAGER_SIZE 512#if defined(PATH_MAX)#if PATH_MAX > 512#define KEYDATA_PATH_SIZE 512#else#define KEYDATA_PATH_SIZE PATH_MAX#endif#else#define KEYDATA_PATH_SIZE 256#endif#ifdef CCXX_NAMESPACESnamespace ost {#endifclass __EXPORT Runlist;class __EXPORT Runable;/** * The memory pager is used to allocate cumulative memory pages for * storing object specific "persistant" data that is presumed to persist * during the life of a given derived object. When the object is * destroyed, all accumulated data is automatically purged. * * There are a number of odd and specialized utility classes found in Common * C++. The most common of these is the "MemPager" class. This is basically * a class to enable page-grouped "cumulative" memory allocation; all * accumulated allocations are dropped during the destructor. This class has * found it's way in a lot of other utility classes in Common C++. * * @author David Sugar <dyfet@ostel.com> * @short Accumulative object memory allocator. */class __EXPORT MemPager{private: friend class String; friend class MemPagerObject; size_t pagesize; unsigned int pages; struct _page { struct _page *next; size_t used; } *page;protected: /** * Allocate first workspace from paged memory. This method * scans all currently allocated blocks for available space * before adding new pages and hence is both slower and more * efficient. * * @param size size of memory to allocate. * @return pointer to allocated memory. */ virtual void* first(size_t size); /** * Allocate memory from either the currently active page, or * allocate a new page for the object. * * @param size size of memory to allocate. * @return pointer to allocated memory. */ virtual void* alloc(size_t size); /** * Allocate a string from the memory pager pool and copy the * string into it's new memory area. This method allocates * memory by first searching for an available page, and then * allocating a new page if no space is found. * * @param str string to allocate and copy into paged memory pool. * @return copy of string from allocated memory. */ char* first(char *str); /** * Allocate a string from the memory pager pool and copy the * string inti it's new memory area. This checks only the * last active page for available space before allocating a * new page. * * @param str string to allocate and copy into paged memory pool. * @return copy of string from allocated memory. */ char* alloc(const char *str); /** * Create a paged memory pool for cumulative storage. This * pool allocates memory in fixed "pagesize" chunks. Ideal * performance is achived when the pool size matches the * system page size. This pool can only exist in derived * objects. * * @param pagesize page size to allocate chunks. */ MemPager(size_t pagesize = 4096); /** * purge the current memory pool. */ void purge(void); /** * Delete the memory pool and all allocated memory. */ virtual ~MemPager();public: /** * Return the total number of pages that have been allocated * for this memory pool. * * @return number of pages allocated. */ inline int getPages(void) {return pages;};};/** * The StackPager provides a repository to stash and retrieve working * data in last-in-first-out order. The use of a mempager to support * it's operation allows storage of arbitrary sized objects with no * fixed limit. * * @author David Sugar <dyfet@ostel.com> * @short last in first out object pager. */class __EXPORT StackPager : protected MemPager{private: typedef struct frame { struct frame *next; char data[1]; } frame_t; frame_t *stack;public: /** * Create a lifo pager as a mempager. * * @param pagesize for memory allocation */ StackPager(size_t pagesize); /** * Push an arbitrary object onto the stack. * * @return stack memory location. * @param object pointer to data * @param size of data. */ void *push(const void *object, size_t size); /** * Push a string onto the stack. * * @return stack memory location. * @param string pointer. */ void *push(const char *string); /** * Retrieve next object from stack. * * @return object. */ void *pull(void); /** * Purge the stack of all objects and memory allocations. */ void purge(void);};/** * The shared mempager uses a mutex to protect key access methods. * This class is used when a mempager will be shared by multiple * threads. * * @author David Sugar <dyfet@ostel.com> * @short mutex protected memory pager. */class __EXPORT SharedMemPager : public MemPager, public Mutex{protected: /** * Create a mempager mutex pool. * * @param pagesize page size for allocation. * @param name a name for the pool. */ SharedMemPager(size_t pagesize = 4096, const char *name = NULL); /** * Purge the memory pool while locked. */ void purge(void); /** * Get the first memory page after locking. * * @return allocated memory space. * @param size of request. */ void* first(size_t size); /** * Get the last memory page after locking. * * @return allocated memory space. * @param size of request. */ void* alloc(size_t size);};/** * Keydata objects are used to load and hold "configuration" data for * a given application. * * This class is used to load and then hold "<code>keyword = value</code>" pairs parsed from a text * based "config" file that has been divided into "<code>[sections]</code>". The syntax is: * * <code><pre> * [section_name] * key1=value1 * key2=value2</pre></code> * * Essentially, the "path" is a "keypath" into a theoretical namespace of key * pairs, hence one does not use "real" filepaths that may be OS dependent. The "<code>/</code>" path refers * to "<code>/etc</code>" prefixed (on UNIX) directories and this is processed within the constructor. It * could refer to the <code>/config</code> prefix on QNX, or even, gasp, a "<code>C:\WINDOWS</code>". Hence, a keypath of * "<code>/bayonne.d/vmhost/smtp</code>" actually resolves to a "<code>/etc/bayonne.d/vmhost.conf</code>" and loads key * value pairs from the <code>[smtp]</code> section of that <code>.conf</code> file. * * Similarly, something like "<code>~bayonne/smtp</code>" path refers to a "<code>~/.bayonnerc</code>" and loads key pairs * from the <code>[smtp]</code> section. This coercion occurs before the name is passed to the open call. * * I actually use derived keydata based classes as global initialized objects, and they hence * automatically load and parse config file entries even before "main" has started. * * Keydata can hold multiple values for the same key pair. This can * occur either from storing a "list" of data items in a config file, * or when overlaying multiple config sources (such as <code>/etc/....conf</code> and * <code>~/.confrc</code> segments) into a single object. The keys are stored as * cumulative (read-only/replacable) config values under a hash index * system for quick retrieval. * * Keydata can * also load a table of "initialization" values for keyword pairs that were * not found in the external file. * * One typically derives an application specific keydata class to load a * specific portion of a known config file and initialize it's values. One * can then declare a global instance of these objects and have * configuration data initialized automatically as the executable is loaded. * * Hence, if I have a "[paths]" section in a "<code>/etc/server.conf?</code>" file, I might * define something like: * * <code><pre> * class KeyPaths : public Keydata * { * public: * KeyPaths() : Keydata("/server/paths") * { * static Keydata::Define *defvalues = { * {"datafiles", "/var/server"}, * {NULL, NULL}}; * * // override with [paths] from "~/.serverrc" if avail. * * load("~server/paths"); * load(defvalues); * } * }; * * KeyPaths keypaths; * </pre></code> * * @author David Sugar <dyfet@ostel.com> * @short load text configuration files into keyword pairs. */class __EXPORT Keydata : protected MemPager{public:#ifdef CCXX_PACKED#pragma pack(1)#endif struct Keyval { Keyval *next; char val[1]; }; struct Keysym { Keysym *next; Keyval *data; const char **list; short count; char sym[1]; }; struct Define { char *keyword; char *value; };#ifdef CCXX_PACKED#pragma pack()#endifprivate: static std::ifstream *cfgFile; static char lastpath[KEYDATA_PATH_SIZE + 1];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -