1. buffer
- The libPhenom buffer API allows for fixed-size buffers to be used reasonably efficiently in an application. The API provides a couple of benefits:
- Slices can be made over a region of another buffer. The slice allows for the region to be referenced without copying, while still safely managing the underlying storage
The object representation of a string buffer means that we can avoid string interning costs when integrating with runtimes such as Lua - Discontiguous buffers can be used to accumulate data. The fixed size of these buffers helps to reduce heap fragmentation. An API is provided to locate and slice (or duplicate if needed) a delimited record (such as CRLF delimited lines)
2. Configuration
- libPhenom provides a relatively simple configuration facility; the process has a global configuration expressed as a variant object.
- There is limited support for mutating the configuration: any values or objects you obtain via the configuration API MUST be treated as read-only as they may be accessed from any thread concurrently.
- If you need to mutate the configuration at runtime (not recommended), then you need to replace the entire configuration object with the new generation of the configuration, and then dispose of the old one.
Counters
The counter subsystem provides a set of functions that allows the application to build a hierarchy of 64-bit counter values.
These values may be modified and queried atomically via the provided API.
Functions are provided to introspect the hierarchy and groups of related counters can be read consistently. Note that the system does not provide a means for snapshotting the entire counter hierarchy.
Counters are implemented such that individual threads may manipulate their values uncontested (with no locking!), but allowing for a reader to obtain a consistent view of a related set of counters.
Base Environment
Including phenom/defs.h sets the base environment for using phenom. This header should be included first (most phenom headers will pull this in explicitly) so that the compilation environment exposes the more modern unix compilation features of your system.
DNS Resolution facilities
libPhenom provides an asynchronous wrapper around the system resolver that delegates to the system provided getaddrinfo() library function but runs in a thread pool.
This is provided for the common case of resolving a target hostname and then setting up an async connect.
The resolver functions operate by schedling a resolution and arrange to invoke a callback when the results are available. The same callback is invoked in both the success and error cases. The callback may be triggered on the same thread that scheduled the resolution, but the common case is for the resolution to complete on some other thread and invoke the callback in that context.
The intended usage is that you schedule a job to continue your processing in some other context.
Hash Table
libPhenom provides a hash table facility that allows the construction of maps from an arbitrary key type to an arbitrary value type.
The hash table uses closed hashing / open addressing to reduce the volume of discrete allocations required to maintain the table.
Note: The tables have no built-in mutex or locking capability. For a concurrent map you might consider using the Concurrency Kit hash-set API. You may alternatively wrap your hash table implementation in an appropriate mutex or reader-writer lock.
Jobs
Jobs describe a parcel of work. Jobs may be triggered or dispatched in one of a number of "run classes". There are three run classes:
- Immediate. The work is dispatched immediately on the calling thread.
- NBIO. The work is dispatched when a descriptor is signalled for I/O.
- Pool. The work is queued to a thread pool and is dispatched as soon as a worker becomes available. libPhenom allows multiple pools to be defined to better partition and prioritize your workload.
JSON Support
libPhenom provides JSON encoding and decoding support functions. These are implemented in terms of the variant datatype; you may encode from a variant to JSON and vice-versa.
Listener
socket服务器端监听绑定过程
Logging
libPhenom provides simple but useful logging utilities.
Each logged message is associated with one of the following severity levels:
-
PH_LOG_PANIC
- the world is going to end -
PH_LOG_ALERT
- take notice this is very import -
PH_LOG_CRIT
- almost as important as alert -
PH_LOG_ERR
- something bad happened; you should probably look at it -
PH_LOG_WARN
- something happened but it may not be actionable -
PH_LOG_NOTICE
- somewhat noisy notification about something -
PH_LOG_INFO
- rather more noisy notification of something -
PH_LOG_DEBUG
- noisy diagnostic mode
The system has an overall log level that specifies the threshold for which log messages will be allowed to hit the underyling logs.
The default is PH_LOG_ERR
, meaning that a log event must be PH_LOG_ERR
or higher for the message to hit the logs.
Expanded log messages have a maximum length of 1024 bytes in the current implementation.
Memory management facility
It is important for long-running infrastructure software to maintain information about its memory usage. This facility allows named memory types to be registered and have stats maintained against them.
OpenSSL
Printf
Reference Counting
Helpers for working with reference counters in C. These delegate to Concurrency Kit and use the primitive fetch-and-add functions (ck_pr_faa_XXX).
Socket
Streams
libPhenom provides a portable layer over streaming IO
Strings
C strings are somewhat bare, so we provide some helpers that aim to assist with:
avoiding heap allocations where possible
tracking heap allocations when not avoidable
safely manage string expansion and growth
Utility Functions
A slightly random set of helper functions.
Spawn
Timer Wheel
This borrows from the concepts explored in the paper: "Hashed and Hierarchical Timing Wheels: Effcient Data Structures for Implementing a Timer Facility by George Varghese and Anthony Lauck"
We model timers as the number of ticks until the next due event. We allow 32-bits of space to track this due interval, and break that into 4 regions of 8 bits. Each region indexes into a bucket of 256 lists.
Bucket 0 represents those events that are due the soonest. Each tick causes us to look at the next list in a bucket. The 0th list in a bucket is special; it means that it is time to flush the timers from the next higher bucket and schedule them into a different bucket.
This technique results in a very cheap mechanism for maintaining time and timers, provided that we can maintain a consistent rate of ticks.
Variant Data Type
Variants can represent runtime variable values and are primarily useful when it comes to serialization to/from the JSON or BSER encoding formats.
Note: JSON requires that all strings be UTF-8 encoded, but these functions won't validate the strings you pass into them because there are situations where binary string support is desirable or essential. You may use ph_string_is_valid_utf8()to check for correctness.