Skip to content

Commit

Permalink
Add Data:performAtomic to lock a mutex while using a Data object.
Browse files Browse the repository at this point in the history
  • Loading branch information
slime73 committed Feb 18, 2024
1 parent 007090a commit ae6800e
Show file tree
Hide file tree
Showing 5 changed files with 58 additions and 14 deletions.
17 changes: 17 additions & 0 deletions src/common/Data.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,27 @@

// LOVE
#include "Data.h"
#include "thread/threads.h"

namespace love
{

love::Type Data::type("Data", &Object::type);

Data::~Data()
{
delete mutex;
}

static void createMutex(love::thread::Mutex **mutexAddress)
{
*mutexAddress = love::thread::newMutex();
}

love::thread::Mutex *Data::getMutex()
{
std::call_once(mutexCreated, createMutex, &mutex);
return mutex;
}

} // love
24 changes: 19 additions & 5 deletions src/common/Data.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,20 @@
#define LOVE_DATA_H

// LOVE
#include "config.h"
#include "Object.h"

// C
#include <stddef.h>
#include <mutex>

namespace love
{

namespace thread
{
class Mutex;
}

/**
* This class is a simple abstraction over all objects which contain data.
**/
Expand All @@ -40,10 +45,8 @@ class Data : public Object

static love::Type type;

/**
* Destructor.
**/
virtual ~Data() {}
Data() {};
virtual ~Data();

/**
* Creates a duplicate of Data derived class instance.
Expand All @@ -60,6 +63,17 @@ class Data : public Object
**/
virtual size_t getSize() const = 0;

/**
* Gets the Mutex associated with this Data object. Creates it in a thread-
* safe manner if necessary.
**/
love::thread::Mutex *getMutex();

private:

love::thread::Mutex *mutex = nullptr;
std::once_flag mutexCreated;

}; // Data

} // love
Expand Down
22 changes: 22 additions & 0 deletions src/modules/data/wrap_Data.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

#include "wrap_Data.h"
#include "common/int.h"
#include "thread/threads.h"

// Put the Lua code directly into a raw string literal.
static const char data_lua[] =
Expand Down Expand Up @@ -78,6 +79,26 @@ int w_Data_getSize(lua_State *L)
return 1;
}

int w_Data_performAtomic(lua_State *L)
{
Data *t = luax_checkdata(L, 1);
int err = 0;

{
love::thread::Lock lock(t->getMutex());
// call the function, passing any user-specified arguments.
err = lua_pcall(L, lua_gettop(L) - 2, LUA_MULTRET, 0);
}

// Unfortunately, this eats the stack trace, too bad.
if (err != 0)
return lua_error(L);

// The function and everything after it in the stack are eaten by the pcall,
// leaving only the Data object. Everything else is a return value.
return lua_gettop(L) - 1;
}

template <typename T>
static int w_Data_getT(lua_State* L)
{
Expand Down Expand Up @@ -170,6 +191,7 @@ const luaL_Reg w_Data_functions[] =
{ "getPointer", w_Data_getPointer },
{ "getFFIPointer", w_Data_getFFIPointer },
{ "getSize", w_Data_getSize },
{ "performAtomic", w_Data_performAtomic },
{ "getFloat", w_Data_getFloat },
{ "getDouble", w_Data_getDouble },
{ "getInt8", w_Data_getInt8 },
Expand Down
5 changes: 0 additions & 5 deletions src/modules/image/ImageData.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -764,11 +764,6 @@ void ImageData::paste(ImageData *src, int dx, int dy, int sx, int sy, int sw, in
}
}

love::thread::Mutex *ImageData::getMutex() const
{
return mutex;
}

size_t ImageData::getPixelSize() const
{
return getPixelFormatBlockSize(format);
Expand Down
4 changes: 0 additions & 4 deletions src/modules/image/ImageData.h
Original file line number Diff line number Diff line change
Expand Up @@ -110,8 +110,6 @@ class ImageData : public ImageDataBase
**/
love::filesystem::FileData *encode(FormatHandler::EncodedFormat format, const char *filename, bool writefile) const;

love::thread::Mutex *getMutex() const;

// Implements ImageDataBase.
ImageData *clone() const override;
void *getData() const override;
Expand Down Expand Up @@ -142,8 +140,6 @@ class ImageData : public ImageDataBase
// The actual data.
unsigned char *data = nullptr;

love::thread::MutexRef mutex;

// The format handler that was used to decode the ImageData. We need to know
// this so we can properly delete memory allocated by the decoder.
StrongRef<FormatHandler> decodeHandler;
Expand Down

0 comments on commit ae6800e

Please sign in to comment.