Initial commit: ROW Client source code
Game client codebase including: - CharacterActionControl: Character and creature management - GlobalScript: Network, items, skills, quests, utilities - RYLClient: Main client application with GUI and event handlers - Engine: 3D rendering engine (RYLGL) - MemoryManager: Custom memory allocation - Library: Third-party dependencies (DirectX, boost, etc.) - Tools: Development utilities 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,265 @@
|
||||
// Copyright (C) 2000, 2001 Stephen Cleary
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org for updates, documentation, and revision history.
|
||||
|
||||
#ifndef BOOST_SIMPLE_SEGREGATED_STORAGE_HPP
|
||||
#define BOOST_SIMPLE_SEGREGATED_STORAGE_HPP
|
||||
|
||||
// std::greater
|
||||
#include <functional>
|
||||
|
||||
#include <boost/pool/poolfwd.hpp>
|
||||
|
||||
namespace boost {
|
||||
|
||||
template <typename SizeType>
|
||||
class simple_segregated_storage
|
||||
{
|
||||
public:
|
||||
typedef SizeType size_type;
|
||||
|
||||
private:
|
||||
simple_segregated_storage(const simple_segregated_storage &);
|
||||
void operator=(const simple_segregated_storage &);
|
||||
|
||||
// pre: (n > 0), (start != 0), (nextof(start) != 0)
|
||||
// post: (start != 0)
|
||||
static void * try_malloc_n(void * & start, size_type n,
|
||||
size_type partition_size);
|
||||
|
||||
protected:
|
||||
void * first;
|
||||
|
||||
// Traverses the free list referred to by "first",
|
||||
// and returns the iterator previous to where
|
||||
// "ptr" would go if it was in the free list.
|
||||
// Returns 0 if "ptr" would go at the beginning
|
||||
// of the free list (i.e., before "first")
|
||||
void * find_prev(void * ptr);
|
||||
|
||||
// for the sake of code readability :)
|
||||
static void * & nextof(void * const ptr)
|
||||
{ return *(static_cast<void **>(ptr)); }
|
||||
|
||||
public:
|
||||
// Post: empty()
|
||||
simple_segregated_storage()
|
||||
:first(0) { }
|
||||
|
||||
// pre: npartition_sz >= sizeof(void *)
|
||||
// npartition_sz = sizeof(void *) * i, for some integer i
|
||||
// nsz >= npartition_sz
|
||||
// block is properly aligned for an array of object of
|
||||
// size npartition_sz and array of void *
|
||||
// The requirements above guarantee that any pointer to a chunk
|
||||
// (which is a pointer to an element in an array of npartition_sz)
|
||||
// may be cast to void **.
|
||||
static void * segregate(void * block,
|
||||
size_type nsz, size_type npartition_sz,
|
||||
void * end = 0);
|
||||
|
||||
// Same preconditions as 'segregate'
|
||||
// Post: !empty()
|
||||
void add_block(void * const block,
|
||||
const size_type nsz, const size_type npartition_sz)
|
||||
{
|
||||
// Segregate this block and merge its free list into the
|
||||
// free list referred to by "first"
|
||||
first = segregate(block, nsz, npartition_sz, first);
|
||||
}
|
||||
|
||||
// Same preconditions as 'segregate'
|
||||
// Post: !empty()
|
||||
void add_ordered_block(void * const block,
|
||||
const size_type nsz, const size_type npartition_sz)
|
||||
{
|
||||
// This (slower) version of add_block segregates the
|
||||
// block and merges its free list into our free list
|
||||
// in the proper order
|
||||
|
||||
// Find where "block" would go in the free list
|
||||
void * const loc = find_prev(block);
|
||||
|
||||
// Place either at beginning or in middle/end
|
||||
if (loc == 0)
|
||||
add_block(block, nsz, npartition_sz);
|
||||
else
|
||||
nextof(loc) = segregate(block, nsz, npartition_sz, nextof(loc));
|
||||
}
|
||||
|
||||
// default destructor
|
||||
|
||||
bool empty() const { return (first == 0); }
|
||||
|
||||
// pre: !empty()
|
||||
void * malloc()
|
||||
{
|
||||
void * const ret = first;
|
||||
|
||||
// Increment the "first" pointer to point to the next chunk
|
||||
first = nextof(first);
|
||||
return ret;
|
||||
}
|
||||
|
||||
// pre: chunk was previously returned from a malloc() referring to the
|
||||
// same free list
|
||||
// post: !empty()
|
||||
void free(void * const chunk)
|
||||
{
|
||||
nextof(chunk) = first;
|
||||
first = chunk;
|
||||
}
|
||||
|
||||
// pre: chunk was previously returned from a malloc() referring to the
|
||||
// same free list
|
||||
// post: !empty()
|
||||
void ordered_free(void * const chunk)
|
||||
{
|
||||
// This (slower) implementation of 'free' places the memory
|
||||
// back in the list in its proper order.
|
||||
|
||||
// Find where "chunk" goes in the free list
|
||||
void * const loc = find_prev(chunk);
|
||||
|
||||
// Place either at beginning or in middle/end
|
||||
if (loc == 0)
|
||||
free(chunk);
|
||||
else
|
||||
{
|
||||
nextof(chunk) = nextof(loc);
|
||||
nextof(loc) = chunk;
|
||||
}
|
||||
}
|
||||
|
||||
// Note: if you're allocating/deallocating n a lot, you should
|
||||
// be using an ordered pool.
|
||||
void * malloc_n(size_type n, size_type partition_size);
|
||||
|
||||
// pre: chunks was previously allocated from *this with the same
|
||||
// values for n and partition_size
|
||||
// post: !empty()
|
||||
// Note: if you're allocating/deallocating n a lot, you should
|
||||
// be using an ordered pool.
|
||||
void free_n(void * const chunks, const size_type n,
|
||||
const size_type partition_size)
|
||||
{
|
||||
add_block(chunks, n * partition_size, partition_size);
|
||||
}
|
||||
|
||||
// pre: chunks was previously allocated from *this with the same
|
||||
// values for n and partition_size
|
||||
// post: !empty()
|
||||
void ordered_free_n(void * const chunks, const size_type n,
|
||||
const size_type partition_size)
|
||||
{
|
||||
add_ordered_block(chunks, n * partition_size, partition_size);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename SizeType>
|
||||
void * simple_segregated_storage<SizeType>::find_prev(void * const ptr)
|
||||
{
|
||||
// Handle border case
|
||||
if (first == 0 || std::greater<void *>()(first, ptr))
|
||||
return 0;
|
||||
|
||||
void * iter = first;
|
||||
while (true)
|
||||
{
|
||||
// if we're about to hit the end or
|
||||
// if we've found where "ptr" goes
|
||||
if (nextof(iter) == 0 || std::greater<void *>()(nextof(iter), ptr))
|
||||
return iter;
|
||||
|
||||
iter = nextof(iter);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename SizeType>
|
||||
void * simple_segregated_storage<SizeType>::segregate(
|
||||
void * const block,
|
||||
const size_type sz,
|
||||
const size_type partition_sz,
|
||||
void * const end)
|
||||
{
|
||||
// Get pointer to last valid chunk, preventing overflow on size calculations
|
||||
// The division followed by the multiplication just makes sure that
|
||||
// old == block + partition_sz * i, for some integer i, even if the
|
||||
// block size (sz) is not a multiple of the partition size.
|
||||
char * old = static_cast<char *>(block)
|
||||
+ ((sz - partition_sz) / partition_sz) * partition_sz;
|
||||
|
||||
// Set it to point to the end
|
||||
nextof(old) = end;
|
||||
|
||||
// Handle border case where sz == partition_sz (i.e., we're handling an array
|
||||
// of 1 element)
|
||||
if (old == block)
|
||||
return block;
|
||||
|
||||
// Iterate backwards, building a singly-linked list of pointers
|
||||
for (char * iter = old - partition_sz; iter != block;
|
||||
old = iter, iter -= partition_sz)
|
||||
nextof(iter) = old;
|
||||
|
||||
// Point the first pointer, too
|
||||
nextof(block) = old;
|
||||
|
||||
return block;
|
||||
}
|
||||
|
||||
// The following function attempts to find n contiguous chunks
|
||||
// of size partition_size in the free list, starting at start.
|
||||
// If it succeds, it returns the last chunk in that contiguous
|
||||
// sequence, so that the sequence is known by [start, {retval}]
|
||||
// If it fails, it does do either because it's at the end of the
|
||||
// free list or hits a non-contiguous chunk. In either case,
|
||||
// it will return 0, and set start to the last considered
|
||||
// chunk. You are at the end of the free list if
|
||||
// nextof(start) == 0. Otherwise, start points to the last
|
||||
// chunk in the contiguous sequence, and nextof(start) points
|
||||
// to the first chunk in the next contiguous sequence (assuming
|
||||
// an ordered free list)
|
||||
template <typename SizeType>
|
||||
void * simple_segregated_storage<SizeType>::try_malloc_n(
|
||||
void * & start, size_type n, const size_type partition_size)
|
||||
{
|
||||
void * iter = nextof(start);
|
||||
while (--n != 0)
|
||||
{
|
||||
void * next = nextof(iter);
|
||||
if (next != static_cast<char *>(iter) + partition_size)
|
||||
{
|
||||
// next == 0 (end-of-list) or non-contiguous chunk found
|
||||
start = iter;
|
||||
return 0;
|
||||
}
|
||||
iter = next;
|
||||
}
|
||||
return iter;
|
||||
}
|
||||
|
||||
template <typename SizeType>
|
||||
void * simple_segregated_storage<SizeType>::malloc_n(const size_type n,
|
||||
const size_type partition_size)
|
||||
{
|
||||
void * start = &first;
|
||||
void * iter;
|
||||
do
|
||||
{
|
||||
if (nextof(start) == 0)
|
||||
return 0;
|
||||
iter = try_malloc_n(start, n, partition_size);
|
||||
} while (iter == 0);
|
||||
void * const ret = nextof(start);
|
||||
nextof(start) = nextof(iter);
|
||||
return ret;
|
||||
}
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user