#ifndef USERLAND_FS_REQUEST_ALLOCATOR_H
#define USERLAND_FS_REQUEST_ALLOCATOR_H
#include <new>
#include <OS.h>
#include "Debug.h"
#include "Requests.h"
namespace UserlandFSUtil {
class Port;
class RequestAllocator {
public:
RequestAllocator(Port* port);
~RequestAllocator();
status_t Init(Port* port);
void Uninit();
status_t Error() const;
void FinishDeferredInit();
status_t AllocateRequest(int32 size);
status_t ReadRequest(bigtime_t timeout);
Request* GetRequest() const;
int32 GetRequestSize() const;
status_t AllocateAddress(Address& address, int32 size,
int32 align, void** data,
bool deferredInit = false, int32 reserveForNextRequests = 0);
status_t AllocateData(Address& address, const void* data,
int32 size, int32 align,
bool deferredInit = false, int32 reserveForNextRequests = 0);
status_t AllocateString(Address& address,
const char* data,
bool deferredInit = false);
private:
struct DeferredInitInfo {
Address* target;
uint8* data;
area_id area;
int32 offset;
int32 size;
bool inPortBuffer;
};
status_t fError;
Port* fPort;
Request* fRequest;
int32 fRequestSize;
int32 fPortReservedOffset;
int32 fRequestOffset;
area_id fAllocatedAreas[MAX_REQUEST_ADDRESS_COUNT];
int32 fAllocatedAreaCount;
DeferredInitInfo fDeferredInitInfos[MAX_REQUEST_ADDRESS_COUNT];
int32 fDeferredInitInfoCount;
bool fRequestInPortBuffer;
};
template<typename SpecificRequest>
status_t
AllocateRequest(RequestAllocator& allocator, SpecificRequest** request)
{
if (!request)
RETURN_ERROR(B_BAD_VALUE);
status_t error = allocator.AllocateRequest(sizeof(SpecificRequest));
if (error == B_OK)
*request = new(allocator.GetRequest()) SpecificRequest;
return error;
}
}
using UserlandFSUtil::RequestAllocator;
using UserlandFSUtil::AllocateRequest;
#endif