I found an article i find quite interesting. There is just one thing i cannot wrap my head around. (http://molecularmusings.wordpress.com/2011/08/31/file-system-part-1-platform-specific-api-design/) The author describes a File class which is able to handle synchronous and asynchronous file operations. For the asynchronous operation he uses a self-contained object which keeps track of the asynchronous operation internally. The class looks like this:
class OsAsyncFileOperation
{
public:
OsAsyncFileOperation(HANDLE file, size_t position);
OsAsyncFileOperation(const OsAsyncFileOperation& other);
OsAsyncFileOperation& operator=(const OsAsyncFileOperation& other);
~OsAsyncFileOperation(void);
/// Returns whether or not the asynchronous operation has finished
bool HasFinished(void) const;
/// Waits until the asynchronous operation has finished. Returns the number of transferred bytes.
size_t WaitUntilFinished(void) const;
/// Cancels the asynchronous operation
void Cancel(void);
private:
HANDLE m_file;
ReferenceCountedItem<OVERLAPPED>* m_overlapped;
};
And is used like this:
OsAsyncFileOperation ReadAsync(void* buffer, size_t length, size_t position);
Now i am wondering: What is the role of the ReferenceCountedItem<OVERLAPPED>* m_overlapped;
variable? I know that this somehow counts the references, but i am not sure how it is used here, especially since the constructor is not getting passed the OVERLAPPED
structure. How does this class now about the OVERLAPPED
structure used in the ReadAsync
or WriteAsync
method?
I tried to implement the ReferenceCountedItem
class, since it is not specified in the article:
#pragma once
template <typename T>
class ReferenceCountedItem {
public:
ReferenceCountedItem(T* data) :m_data(data), m_refCounter(1)
{}
~ReferenceCountedItem() {}
int addReference()
{
return ++this->m_refCounter;
}
int removeReference()
{
return --this->m_refCounter;
}
private:
T* m_data;
int m_refCounter;
};
I am mostly unsure of how this all is sticking together. Maybe someone can explain a little bit more about it. If you need more information please let me know.
Somewhere the author is allocating the OVERLAPPED struct on the heap, with new
or GlobalAlloc
. Then, in the copy constructor and operator=
, he is copying the pointer. Since there can be multiple objects using the pointer he is using reference counting to know when it's ok to delete the OVERLAPPED pointer.