1// RequestAllocator.h
2
3#ifndef USERLAND_FS_REQUEST_ALLOCATOR_H
4#define USERLAND_FS_REQUEST_ALLOCATOR_H
5
6#include <new>
7
8#include <OS.h>
9
10#include "Debug.h"
11#include "Requests.h"
12
13namespace UserlandFSUtil {
14
15class Port;
16
17// RequestAllocator
18class RequestAllocator {
19public:
20								RequestAllocator(Port* port);
21								~RequestAllocator();
22
23			status_t			Init(Port* port);
24			void				Uninit();
25
26			status_t			Error() const;
27
28			void				FinishDeferredInit();
29
30			status_t			AllocateRequest(int32 size);
31			status_t			ReadRequest();
32
33			Request*			GetRequest() const;
34			int32				GetRequestSize() const;
35
36			status_t			AllocateAddress(Address& address, int32 size,
37									int32 align, void** data,
38									bool deferredInit = false);
39			status_t			AllocateData(Address& address, const void* data,
40									int32 size, int32 align,
41									bool deferredInit = false);
42			status_t			AllocateString(Address& address,
43									const char* data,
44									bool deferredInit = false);
45//			status_t			SetAddress(Address& address, void* data,
46//									int32 size = 0);
47
48private:
49			struct DeferredInitInfo {
50				Address*	target;
51				uint8*		data;		// only if in port buffer
52				area_id		area;		// only if in area, otherwise -1
53				int32		offset;
54				int32		size;
55				bool		inPortBuffer;
56			};
57
58			status_t			fError;
59			Port*				fPort;
60			Request*			fRequest;
61			int32				fRequestSize;
62			area_id				fAllocatedAreas[MAX_REQUEST_ADDRESS_COUNT];
63			int32				fAllocatedAreaCount;
64			DeferredInitInfo	fDeferredInitInfos[MAX_REQUEST_ADDRESS_COUNT];
65			int32				fDeferredInitInfoCount;
66			bool				fRequestInPortBuffer;
67};
68
69// AllocateRequest
70// Should be a member, but we don't have member templates on PPC.
71// TODO: Actually we seem to have. Check!
72template<typename SpecificRequest>
73status_t
74AllocateRequest(RequestAllocator& allocator, SpecificRequest** request)
75{
76	if (!request)
77		RETURN_ERROR(B_BAD_VALUE);
78	status_t error = allocator.AllocateRequest(sizeof(SpecificRequest));
79	if (error == B_OK)
80		*request = new(allocator.GetRequest()) SpecificRequest;
81	return error;
82}
83
84}	// namespace UserlandFSUtil
85
86using UserlandFSUtil::RequestAllocator;
87using UserlandFSUtil::AllocateRequest;
88
89#endif	// USERLAND_FS_REQUEST_ALLOCATOR_H
90