Sfoglia il codice sorgente

add and use ReadWriteLock instead of Critical when possible

Kolja Strohm 1 settimana fa
parent
commit
65b085903e
42 ha cambiato i file con 1116 aggiunte e 765 eliminazioni
  1. 22 22
      Animation.cpp
  2. 7 11
      Animation.h
  3. 10 10
      Button.cpp
  4. 6 5
      Camera2D.cpp
  5. 265 0
      Critical.cpp
  6. 41 0
      Critical.h
  7. 50 18
      DX11GraphicsApi.cpp
  8. 14 5
      DXBuffer.cpp
  9. 8 3
      DXBuffer.h
  10. 153 163
      Diagram.cpp
  11. 25 23
      Diagram.h
  12. 26 27
      Drawing.cpp
  13. 33 32
      Drawing.h
  14. 0 2
      Framework Linux.vcxproj
  15. 0 2
      Framework.vcxproj
  16. 0 6
      Framework.vcxproj.filters
  17. 7 2
      Global.cpp
  18. 1 1
      Globals.h
  19. 12 10
      GraphicsApi.cpp
  20. 12 8
      GraphicsApi.h
  21. 12 14
      Image.cpp
  22. 3 3
      List.cpp
  23. 11 8
      Progress.cpp
  24. 9 9
      RenderThread.cpp
  25. 5 9
      RenderThread.h
  26. 60 61
      Screen.cpp
  27. 26 30
      Screen.h
  28. 37 26
      SelectionBox.cpp
  29. 18 8
      Shader.cpp
  30. 12 8
      Shader.h
  31. 77 105
      Table.cpp
  32. 40 48
      TextField.cpp
  33. 10 2
      Texture.cpp
  34. 6 3
      Texture.h
  35. 2 2
      Texture2D.cpp
  36. 33 43
      TextureList.cpp
  37. 2 8
      TextureList.h
  38. 6 0
      Thread.cpp
  39. 2 1
      Thread.h
  40. 14 5
      Window.cpp
  41. 30 14
      World3D.cpp
  42. 9 8
      World3D.h

+ 22 - 22
Animation.cpp

@@ -27,14 +27,14 @@ Animation2DData::~Animation2DData()
 }
 
 // non-constant
-void Animation2DData::lock()
+Lock& Animation2DData::readLock()
 {
-    cs.lock();
+    return rwLock.getReadLock();
 }
 
-void Animation2DData::unlock()
+Lock& Animation2DData::writeLock()
 {
-    cs.unlock();
+    return rwLock.getWriteLock();
 }
 
 void Animation2DData::loadAnimation(InitFile* datei)
@@ -42,7 +42,7 @@ void Animation2DData::loadAnimation(InitFile* datei)
     if (!datei) return;
     reset();
     int anz = datei->getValueCount();
-    lock();
+    rwLock.lockWrite();
     if (datei->valueExists("fps"))
     {
         --anz;
@@ -94,7 +94,7 @@ void Animation2DData::loadAnimation(InitFile* datei)
             this->bilder[i - j] = bilder[i];
     }
     delete[] bilder;
-    unlock();
+    rwLock.unlockWrite();
     datei->release();
 }
 
@@ -105,7 +105,7 @@ void Animation2DData::loadAnimation(LTDBFile* datei)
     datei->readData(0);
     int anz = datei->getImageCount();
     RCArray<Text>* list = datei->zImageListe();
-    lock();
+    rwLock.lockWrite();
     Image** bilder = new Image*[anz];
     for (int i = 0; i < anz; ++i)
     {
@@ -122,7 +122,7 @@ void Animation2DData::loadAnimation(LTDBFile* datei)
             this->bilder[i - j] = bilder[i];
     }
     delete[] bilder;
-    unlock();
+    rwLock.unlockWrite();
     datei->release();
 }
 
@@ -143,7 +143,7 @@ void Animation2DData::setTransparent(bool trp)
 
 void Animation2DData::reset()
 {
-    lock();
+    rwLock.lockWrite();
     for (int i = 0; i < imageCount; ++i)
         bilder[i] = (Image*)bilder[i]->release();
     delete[] bilder;
@@ -152,7 +152,7 @@ void Animation2DData::reset()
     fps = 30;
     repeat = 0;
     transparent = 0;
-    unlock();
+    rwLock.unlockWrite();
 }
 
 // constant
@@ -236,11 +236,11 @@ void Animation2D::setBorderColor(int f)
 
 void Animation2D::setAnimationDataZ(Animation2DData* data)
 {
-    lockDrawable();
+    rwLock.lockWrite();
     if (this->data) this->data->release();
     this->data = data;
     if (alpha) rend = 1;
-    unlockDrawable();
+    rwLock.unlockWrite();
 }
 
 void Animation2D::setAlphaMaske(unsigned char alpha)
@@ -260,12 +260,12 @@ void Animation2D::setVisible(bool visible)
 
 bool Animation2D::tick(double zeit)
 {
-    lockDrawable();
+    rwLock.lockRead();
     if (!data || (!alpha && !visible))
     {
         bool ret = rend;
         rend = 0;
-        unlockDrawable();
+        rwLock.unlockRead();
         return ret;
     }
     if (visible && alpha < maxAlpha)
@@ -286,7 +286,7 @@ bool Animation2D::tick(double zeit)
     }
     compensation += zeit;
     int tmp = now;
-    data->lock();
+    data->readLock().lock();
     if (compensation >= 1.0 / data->getFPS())
     {
         compensation -= 1.0 / data->getFPS();
@@ -299,22 +299,22 @@ bool Animation2D::tick(double zeit)
                 now = data->getImageCount();
         }
     }
-    data->unlock();
+    data->readLock().unlock();
     if (tmp != now) rend = 1;
-    unlockDrawable();
+    rwLock.unlockRead();
     return Drawable::tick(zeit);
 }
 
 void Animation2D::render(Image& zRObj)
 {
-    lockDrawable();
+    rwLock.lockRead();
     if (!data)
     {
-        unlockDrawable();
+        rwLock.unlockRead();
         return;
     }
     Drawable::render(zRObj);
-    data->lock();
+    data->readLock().lock();
     if (data->zImage(now))
     {
         zRObj.setAlpha(alpha);
@@ -330,8 +330,8 @@ void Animation2D::render(Image& zRObj)
         }
         zRObj.releaseAlpha();
     }
-    data->unlock();
-    unlockDrawable();
+    data->readLock().unlock();
+    rwLock.unlockRead();
 }
 
 // constant

+ 7 - 11
Animation.h

@@ -6,10 +6,10 @@
 
 namespace Framework
 {
-    class Image;      //! Image.h
+    class Image;    //! Image.h
     class LTDBFile; //! FileSystem.h
     class InitFile; //! InitFile.h
-    class Border;    //! Border.h
+    class Border;   //! Border.h
 
     //! Contains all images of a video animation
     class Animation2DData : public virtual ReferenceCounter
@@ -20,21 +20,17 @@ namespace Framework
         int fps;
         bool repeat;
         bool transparent;
-        Critical cs;
+        ReadWriteLock rwLock;
 
     public:
         //! Constructor
         DLLEXPORT Animation2DData();
         //! Destructor
         DLLEXPORT ~Animation2DData();
-        //! This is necessary if multiple threads use this object simultaneously.
-        //! If lock() is called by two threads, the last one waits until the
-        //! first one has called unlock().
-        DLLEXPORT void lock();
-        //! This is necessary if multiple threads use this object simultaneously.
-        //! If lock() is called by two threads, the last one waits until the
-        //! first one has called unlock().
-        DLLEXPORT void unlock();
+        //! returns a lock for reading the animation data.
+        DLLEXPORT Lock& readLock();
+        //! returns a lock for writing the animation data.
+        DLLEXPORT Lock& writeLock();
         //! Loads all images from an InitFile. The values 'fps',
         //! 'repeat' (true, false), 'transparent' (true, false) are also
         //! interpreted. The images must be in the correct order in the file.

+ 10 - 10
Button.cpp

@@ -1,15 +1,15 @@
 #include "Button.h"
 
 #include "AlphaField.h"
-#include "Image.h"
+#include "Border.h"
 #include "File.h"
 #include "FileSystem.h"
+#include "Font.h"
 #include "Globals.h"
+#include "Image.h"
+#include "KeyboardEvent.h"
 #include "MouseEvent.h"
-#include "Border.h"
-#include "Font.h"
 #include "Scroll.h"
-#include "KeyboardEvent.h"
 #include "Text.h"
 #include "ToolTip.h"
 
@@ -252,7 +252,8 @@ Button::duplicate() const // creates a copy of the drawing and returns it
     obj->setSchowChar(getShowChar());
     // obj->setSelection( getSelectionPos(), getCursorPos() );
     obj->setClickColor(klickColor);
-    if (clickImage) obj->setClickImage(dynamic_cast<Image*>(clickImage->getThis()));
+    if (clickImage)
+        obj->setClickImage(dynamic_cast<Image*>(clickImage->getThis()));
     if (klickBuffer) obj->setKBZ((AlphaField*)klickBuffer->duplicate());
     return obj;
 }
@@ -470,8 +471,7 @@ void CheckBox::setClickAFStrength(int st) // sets the click AlphaField strength
 
 void CheckBox::loadData(LTDBFile* dat) // loading the system images
 {
-    if (FileExists(new Text("data/normal.ltdb"))
-        && (!dat || !dat->isOpen()))
+    if (FileExists(new Text("data/normal.ltdb")) && (!dat || !dat->isOpen()))
     {
         LTDBFile* dat = new LTDBFile();
         dat->setFile(new Text("data/normal.ltdb"));
@@ -508,10 +508,10 @@ void CheckBox::render(Image& zRObj) // renders into zRObj
     if (!hasStyle(Style::Visible)) return;
     removeStyle(Style::VScroll | Style::HScroll);
     DrawableBackground::render(zRObj);
-    lockDrawable();
+    rwLock.lockRead();
     if (!zRObj.setDrawOptions(innenPosition, innenSize))
     {
-        unlockDrawable();
+        rwLock.unlockRead();
         return;
     }
     if (hasStyle(Style::MouseClick))
@@ -681,7 +681,7 @@ void CheckBox::render(Image& zRObj) // renders into zRObj
         }
     }
     zRObj.releaseDrawOptions();
-    unlockDrawable();
+    rwLock.unlockRead();
 }
 
 // constant

+ 6 - 5
Camera2D.cpp

@@ -1,7 +1,7 @@
 #include "Camera2D.h"
 
-#include "Image.h"
 #include "Globals.h"
+#include "Image.h"
 #include "World2D.h"
 
 using namespace Framework;
@@ -40,7 +40,8 @@ void Camera2D::lookAtWorldPos(float x, float y)
     rend |= wPos != Vertex(x, y);
     wPos.x = x;
     wPos.y = y;
-    if (world && world->getWorldInfo().hasSize && world->getWorldInfo().circular)
+    if (world && world->getWorldInfo().hasSize
+        && world->getWorldInfo().circular)
     {
         if (wPos.x < 0) wPos.x += (float)world->getWorldInfo().size.x;
         if (wPos.y < 0) wPos.y += (float)world->getWorldInfo().size.y;
@@ -93,10 +94,10 @@ void Camera2D::render(Image& zRObj)
     if (hasStyleNot(Style::Visible)) return;
     DrawableBackground::render(zRObj);
     if (!world) return;
-    lockDrawable();
+    rwLock.lockRead();
     if (!zRObj.setDrawOptions(innenPosition, innenSize))
     {
-        unlockDrawable();
+        rwLock.unlockRead();
         return;
     }
     matrix = Mat3<float>::translation((Vertex)gr / 2)
@@ -104,7 +105,7 @@ void Camera2D::render(Image& zRObj)
            * Mat3<float>::translation(-wPos);
     world->render(matrix, gr, zRObj, *name);
     zRObj.releaseDrawOptions();
-    unlockDrawable();
+    rwLock.unlockRead();
 }
 
 Vertex Camera2D::getWorldCoordinates(Point screenPos)

+ 265 - 0
Critical.cpp

@@ -195,3 +195,268 @@ Framework::CriticalLock::~CriticalLock()
     }
     delete[] criticals;
 }
+
+class Framework::InternalReadLock : public Lock
+{
+private:
+    ReadWriteLock* rwLock;
+
+public:
+    InternalReadLock(ReadWriteLock* rwLock)
+        : rwLock(rwLock)
+    {}
+
+    virtual ~InternalReadLock() = default;
+
+    void lock() override
+    {
+        rwLock->lockRead();
+    }
+
+    void unlock() override
+    {
+        rwLock->unlockRead();
+    }
+
+    bool tryLock() override
+    {
+        return rwLock->tryLockRead();
+    }
+};
+
+class Framework::InternalWriteLock : public Lock
+{
+private:
+    ReadWriteLock* rwLock;
+
+public:
+    InternalWriteLock(ReadWriteLock* rwLock)
+        : rwLock(rwLock)
+    {}
+
+    virtual ~InternalWriteLock() = default;
+
+    void lock() override
+    {
+        rwLock->lockWrite();
+    }
+
+    void unlock() override
+    {
+        rwLock->unlockWrite();
+    }
+
+    bool tryLock() override
+    {
+        return rwLock->tryLockWrite();
+    }
+};
+
+Framework::ReadWriteLock::ReadWriteLock(int initialMaxSize)
+    : readerThreads(new int[initialMaxSize]),
+      readCounters(new int[initialMaxSize]),
+      maxSize(initialMaxSize),
+      readerThreadCount(0),
+      writerThread(0),
+      writerCount(0),
+      waitingReaders(0),
+      waitingWriters(0),
+      readLock(new InternalReadLock(this)),
+      writeLock(new InternalWriteLock(this))
+{
+    memset(readerThreads, 0, sizeof(int) * initialMaxSize);
+    memset(readCounters, 0, sizeof(int) * initialMaxSize);
+}
+
+Framework::ReadWriteLock::~ReadWriteLock()
+{
+    delete[] readerThreads;
+    delete[] readCounters;
+    delete readLock;
+    delete writeLock;
+}
+
+void Framework::ReadWriteLock::lockRead()
+{
+    cs.lock();
+    while (writerCount > 0 && writerThread != currentThreadId)
+    {
+        waitingReaders++;
+        cs.unlock();
+        readerBlock.wait();
+        cs.lock();
+        waitingReaders--;
+    }
+    int index = -1;
+    for (int i = 0; i < readerThreadCount; i++)
+    {
+        if (readerThreads[i] == currentThreadId)
+        {
+            index = i;
+            break;
+        }
+    }
+    if (index == -1)
+    {
+        if (readerThreadCount == maxSize)
+        {
+            int* newReaderThreads = new int[maxSize * 2];
+            int* newReadCounters = new int[maxSize * 2];
+            for (int i = 0; i < maxSize; i++)
+            {
+                newReaderThreads[i] = readerThreads[i];
+                newReadCounters[i] = readCounters[i];
+            }
+            delete[] readerThreads;
+            delete[] readCounters;
+            readerThreads = newReaderThreads;
+            readCounters = newReadCounters;
+            maxSize *= 2;
+        }
+        index = readerThreadCount++;
+        readerThreads[index] = currentThreadId;
+    }
+    readCounters[index]++;
+    cs.unlock();
+}
+
+void Framework::ReadWriteLock::lockWrite()
+{
+    cs.lock();
+    while (
+        (writerCount > 0 && writerThread != currentThreadId)
+        || (readerThreadCount > 0
+            && (readerThreadCount != 1 || readerThreads[0] != currentThreadId)))
+    {
+        waitingWriters++;
+        cs.unlock();
+        writerBlock.wait();
+        cs.lock();
+        waitingWriters--;
+    }
+    writerThread = currentThreadId;
+    writerCount++;
+    cs.unlock();
+}
+
+void Framework::ReadWriteLock::unlockRead()
+{
+    cs.lock();
+    int index = -1;
+    for (int i = 0; i < readerThreadCount; i++)
+    {
+        if (readerThreads[i] == currentThreadId)
+        {
+            index = i;
+            break;
+        }
+    }
+    if (index == -1 || readCounters[index] == 0)
+    {
+        cs.unlock();
+        throw "A Thread that does not hold a read lock tries to unlock it";
+    }
+    readCounters[index]--;
+    if (readCounters[index] == 0)
+    {
+        readerThreads[index] = readerThreads[readerThreadCount - 1];
+        readCounters[index] = readCounters[readerThreadCount - 1];
+        readerThreadCount--;
+    }
+    if (readerThreadCount == 0 && waitingWriters > 0)
+    {
+        writerBlock.notify();
+    }
+    cs.unlock();
+}
+
+void Framework::ReadWriteLock::unlockWrite()
+{
+    cs.lock();
+    if (writerThread != currentThreadId || writerCount == 0)
+    {
+        cs.unlock();
+        throw "A Thread that does not hold the write lock tries to unlock it";
+    }
+    writerCount--;
+    if (writerCount == 0)
+    {
+        if (waitingWriters > 0)
+        {
+            writerBlock.notify();
+        }
+        else if (waitingReaders > 0)
+        {
+            readerBlock.notify(waitingReaders);
+        }
+    }
+    cs.unlock();
+}
+
+bool Framework::ReadWriteLock::tryLockRead()
+{
+    cs.lock();
+    if (writerCount > 0 && writerThread != currentThreadId)
+    {
+        cs.unlock();
+        return false;
+    }
+    int index = -1;
+    for (int i = 0; i < readerThreadCount; i++)
+    {
+        if (readerThreads[i] == currentThreadId)
+        {
+            index = i;
+            break;
+        }
+    }
+    if (index == -1)
+    {
+        if (readerThreadCount == maxSize)
+        {
+            int* newReaderThreads = new int[maxSize * 2];
+            int* newReadCounters = new int[maxSize * 2];
+            for (int i = 0; i < maxSize; i++)
+            {
+                newReaderThreads[i] = readerThreads[i];
+                newReadCounters[i] = readCounters[i];
+            }
+            delete[] readerThreads;
+            delete[] readCounters;
+            readerThreads = newReaderThreads;
+            readCounters = newReadCounters;
+            maxSize *= 2;
+        }
+        index = readerThreadCount++;
+        readerThreads[index] = currentThreadId;
+    }
+    readCounters[index]++;
+    cs.unlock();
+    return true;
+}
+
+bool Framework::ReadWriteLock::tryLockWrite()
+{
+    cs.lock();
+    if ((writerCount > 0 && writerThread != currentThreadId)
+        || (readerThreadCount > 0
+            && (readerThreadCount != 1 || readerThreads[0] != currentThreadId)))
+    {
+        cs.unlock();
+        return false;
+    }
+    writerThread = currentThreadId;
+    writerCount++;
+    cs.unlock();
+    return true;
+}
+
+Lock& Framework::ReadWriteLock::getReadLock() const
+{
+    return *readLock;
+}
+
+Lock& Framework::ReadWriteLock::getWriteLock() const
+{
+    return *writeLock;
+}

+ 41 - 0
Critical.h

@@ -69,4 +69,45 @@ namespace Framework
 
         DLLEXPORT int getNumberOfWaitingThreads() const;
     };
+
+    class Lock
+    {
+    public:
+        virtual void lock() = 0;
+        virtual bool tryLock() = 0;
+        virtual void unlock() = 0;
+    };
+
+    class InternalReadLock;
+    class InternalWriteLock;
+
+    class ReadWriteLock
+    {
+    private:
+        int* readerThreads;
+        int* readCounters;
+        int maxSize;
+        int readerThreadCount;
+        int writerThread;
+        int writerCount;
+        int waitingReaders;
+        int waitingWriters;
+        Critical cs;
+        Synchronizer readerBlock;
+        Synchronizer writerBlock;
+        InternalReadLock* readLock;
+        InternalWriteLock* writeLock;
+
+    public:
+        DLLEXPORT ReadWriteLock(int initialMaxSize = 10);
+        DLLEXPORT ~ReadWriteLock();
+        DLLEXPORT void lockRead();
+        DLLEXPORT void lockWrite();
+        DLLEXPORT void unlockRead();
+        DLLEXPORT void unlockWrite();
+        DLLEXPORT bool tryLockRead();
+        DLLEXPORT bool tryLockWrite();
+        DLLEXPORT Lock& getReadLock() const;
+        DLLEXPORT Lock& getWriteLock() const;
+    };
 } // namespace Framework

+ 50 - 18
DX11GraphicsApi.cpp

@@ -1,13 +1,12 @@
 #include <d3d11.h>
 #include <dxgi1_5.h>
 
-#include "Image.h"
+#include "Camera3D.h"
 #include "DLLRegister.h"
 #include "DXBuffer.h"
-#include "Window.h"
 #include "Globals.h"
 #include "GraphicsApi.h"
-#include "Camera3D.h"
+#include "Image.h"
 #include "Logging.h"
 #include "Model3DList.h"
 #include "Shader.h"
@@ -16,6 +15,7 @@
 #include "TextureModel.h"
 #include "UIPixelShader.h"
 #include "UIVertexShader.h"
+#include "Window.h"
 #include "World3D.h"
 
 using namespace Framework;
@@ -308,7 +308,9 @@ void DirectX11::initialize(
     d3d11Context->RSSetViewports(1, vp);
 
     // Create the render target view with the back buffer pointer.
+    deviceLock.lock();
     result = d3d11Device->CreateRenderTargetView(backBufferPtr, NULL, &rtview);
+    deviceLock.unlock();
     if (result != S_OK)
     {
         Logging::error()
@@ -335,8 +337,10 @@ void DirectX11::initialize(
     depthBufferDesc.Usage = D3D11_USAGE_DEFAULT;
     depthBufferDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL;
     // Create the texture for the depth buffer using the filled out description.
+    deviceLock.lock();
     result = d3d11Device->CreateTexture2D(
         &depthBufferDesc, NULL, &depthStencilBuffer);
+    deviceLock.unlock();
     if (result != S_OK)
     {
         Logging::error() << "ERROR: d3d11Device->CreateTexture2D returned "
@@ -369,8 +373,10 @@ void DirectX11::initialize(
     depthStencilDesc.BackFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
     depthStencilDesc.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
     // Create the depth stencil state.
+    deviceLock.lock();
     result = d3d11Device->CreateDepthStencilState(
         &depthStencilDesc, &depthStencilState);
+    deviceLock.unlock();
     if (result != S_OK)
     {
         Logging::error()
@@ -393,8 +399,10 @@ void DirectX11::initialize(
     depthStencilViewDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
 
     // Create the depth stencil view.
+    deviceLock.lock();
     result = d3d11Device->CreateDepthStencilView(
         depthStencilBuffer, &depthStencilViewDesc, &dsView);
+    deviceLock.unlock();
     if (result != S_OK)
     {
         Logging::error()
@@ -433,8 +441,10 @@ void DirectX11::initialize(
     depthDisabledStencilDesc.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
 
     // Create the state using the device.
+    deviceLock.lock();
     result = d3d11Device->CreateDepthStencilState(
         &depthDisabledStencilDesc, &depthDisabledStencilState);
+    deviceLock.unlock();
     if (result != S_OK)
     {
         Logging::error()
@@ -471,7 +481,9 @@ void DirectX11::initialize(
     samplerDesc.MaxLOD = D3D11_FLOAT32_MAX;
 
     // Create the texture sampler state.
+    deviceLock.lock();
     result = d3d11Device->CreateSamplerState(&samplerDesc, &sampleState);
+    deviceLock.unlock();
     if (result != S_OK)
     {
         Logging::error() << "ERROR: d3d11Device->CreateSamplerState returned "
@@ -509,7 +521,9 @@ void DirectX11::initialize(
     blendState.RenderTarget[0].RenderTargetWriteMask
         = D3D11_COLOR_WRITE_ENABLE_ALL;
 
+    deviceLock.lock();
     d3d11Device->CreateBlendState(&blendState, &blendStateAlphaBlend);
+    deviceLock.unlock();
     d3d11Context->OMSetBlendState(blendStateAlphaBlend, 0, 0xFFFFFFFF);
 
     // Setup Render Objekt
@@ -529,7 +543,9 @@ void DirectX11::initialize(
     rasterDesc.MultisampleEnable = false;
     rasterDesc.ScissorEnable = false;
     rasterDesc.SlopeScaledDepthBias = 0.0f;
+    deviceLock.lock();
     d3d11Device->CreateRasterizerState(&rasterDesc, &texturRS);
+    deviceLock.unlock();
 
     ZeroMemory(&rasterDesc, sizeof(rasterDesc));
     rasterDesc.AntialiasedLineEnable = false;
@@ -541,7 +557,9 @@ void DirectX11::initialize(
     rasterDesc.MultisampleEnable = false;
     rasterDesc.ScissorEnable = false;
     rasterDesc.SlopeScaledDepthBias = 0.0f;
+    deviceLock.lock();
     d3d11Device->CreateRasterizerState(&rasterDesc, &meshRS);
+    deviceLock.unlock();
 
     d3d11Context->RSSetState(texturRS);
 
@@ -550,9 +568,9 @@ void DirectX11::initialize(
     defaultTexture = createOrGetTexture("_default_textur", b);
 
     diffuseLights = new DX11StructuredBuffer(
-        sizeof(DiffuseLight), d3d11Device, d3d11Context);
+        sizeof(DiffuseLight), d3d11Device, d3d11Context, deviceLock);
     pointLights = new DX11StructuredBuffer(
-        sizeof(PointLight), d3d11Device, d3d11Context);
+        sizeof(PointLight), d3d11Device, d3d11Context, deviceLock);
 }
 
 void DirectX11::update()
@@ -838,7 +856,7 @@ void DirectX11::renderKamera(Cam3D* zKamera)
     if (pixelShader)
         pixelShader->fillConstBuffer((char*)&kamPos, 0, sizeof(float) * 3);
     World3D* w = zKamera->zWorld();
-    w->lock();
+    w->readLock().lock();
     int lc[] = {w->getDiffuseLightCount(), w->getPointLightCount()};
     pixelShader->fillConstBuffer((char*)lc, 2, sizeof(int) * 2);
     w->copyLight(diffuseLights, pointLights);
@@ -874,8 +892,7 @@ void DirectX11::renderKamera(Cam3D* zKamera)
             if (isInFrustrum(obj->getPos(), obj->getRadius(), &dist))
             {
                 int pos = (int)dist - minDist;
-                sorted[pos * alphaModels.getEntryCount() + index[pos]++]
-                    = obj;
+                sorted[pos * alphaModels.getEntryCount() + index[pos]++] = obj;
             }
         }
         for (int i = 0; i < size; i++)
@@ -888,7 +905,7 @@ void DirectX11::renderKamera(Cam3D* zKamera)
         delete[] index;
         delete[] sorted;
     }
-    w->unlock();
+    w->readLock().unlock();
 }
 
 void DirectX11::renderKamera(Cam3D* zKamera, Texture* zTarget)
@@ -914,8 +931,10 @@ void DirectX11::renderKamera(Cam3D* zKamera, Texture* zTarget)
     depthBufferDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL;
     ID3D11Texture2D* txtDepthStencilBuffer;
     // Create the texture for the depth buffer using the filled out description.
+    deviceLock.lock();
     HRESULT result = d3d11Device->CreateTexture2D(
         &depthBufferDesc, NULL, &txtDepthStencilBuffer);
+    deviceLock.unlock();
     if (result != S_OK) throw "could not create depth Stencil buffer";
     // Initialize the depth stencil view.
     D3D11_DEPTH_STENCIL_VIEW_DESC depthStencilViewDesc;
@@ -927,16 +946,20 @@ void DirectX11::renderKamera(Cam3D* zKamera, Texture* zTarget)
 
     ID3D11DepthStencilView* txtDsView;
     // Create the depth stencil view.
+    deviceLock.lock();
     result = d3d11Device->CreateDepthStencilView(
         txtDepthStencilBuffer, &depthStencilViewDesc, &txtDsView);
+    deviceLock.unlock();
     if (result != S_OK) throw "could not create depth stencil view";
 
     D3D11_RENDER_TARGET_VIEW_DESC renderTargetViewDesc;
     renderTargetViewDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
     renderTargetViewDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
     renderTargetViewDesc.Texture2D.MipSlice = 0;
+    deviceLock.lock();
     result = d3d11Device->CreateRenderTargetView(
         (ID3D11Texture2D*)*d11Textur, &renderTargetViewDesc, &texturRtView);
+    deviceLock.unlock();
     if (result != S_OK)
         throw "could not create render target view for given texture";
     d3d11Context->OMSetRenderTargets(1, &texturRtView, txtDsView);
@@ -981,7 +1004,9 @@ void DirectX11::presentFrame()
     HRESULT result = d3d11SpawChain->Present(0, 0);
     if (!SUCCEEDED(result))
     {
+        deviceLock.lock();
         HRESULT res = d3d11Device->GetDeviceRemovedReason();
+        deviceLock.unlock();
         update();
         WMessageBox(fenster ? fenster->getWindowHandle() : 0,
             new Text("Fehler"),
@@ -1008,7 +1033,7 @@ Texture* DirectX11::createOrGetTexture(const char* name, Image* b)
         if (b) ret->setImageZ(b);
         return ret;
     }
-    Texture* ret = new DX11Texture(d3d11Device, d3d11Context);
+    Texture* ret = new DX11Texture(d3d11Device, d3d11Context, deviceLock);
     if (b) ret->setImageZ(b);
     texturRegister->addTexture(dynamic_cast<Texture*>(ret->getThis()), name);
     return ret;
@@ -1115,21 +1140,27 @@ bool DirectX11::isAvailable()
 
 DXBuffer* DirectX11::createIndexBuffer()
 {
-    return new DX11Buffer(
-        sizeof(int), d3d11Device, d3d11Context, D3D11_BIND_INDEX_BUFFER);
+    return new DX11Buffer(sizeof(int),
+        d3d11Device,
+        d3d11Context,
+        D3D11_BIND_INDEX_BUFFER,
+        deviceLock);
 }
 
 DXBuffer* DirectX11::createVertexBuffer()
 {
-    return new DX11Buffer(
-        sizeof(Vertex3D), d3d11Device, d3d11Context, D3D11_BIND_VERTEX_BUFFER);
+    return new DX11Buffer(sizeof(Vertex3D),
+        d3d11Device,
+        d3d11Context,
+        D3D11_BIND_VERTEX_BUFFER,
+        deviceLock);
 }
 
 DX11VertexShader* DirectX11::initializeVertexShader(
     unsigned char* byteCode, int size)
 {
     DX11VertexShader* vertexShader
-        = new DX11VertexShader(d3d11Device, d3d11Context);
+        = new DX11VertexShader(d3d11Device, d3d11Context, deviceLock);
     vertexShader->setCompiledByteArray(byteCode, size);
     D3D11_INPUT_ELEMENT_DESC polygonLayout[5];
     // Create the vertex input layout description.
@@ -1179,7 +1210,7 @@ DX11VertexShader* DirectX11::initializeVertexShader(
     vertexShader->createConstBuffer(sizeof(Mat4<float>) * MAX_KNOCHEN_ANZ,
         vertexShader
             ->getFirstUninitializedBufferIndex()); // matrices for skeleton
-                                                    // animations
+                                                   // animations
     vertexShader->createConstBuffer(sizeof(Mat4<float>) * 2,
         vertexShader
             ->getFirstUninitializedBufferIndex()); // View and Projection Matrix
@@ -1190,7 +1221,7 @@ DX11PixelShader* DirectX11::initializePixelShader(
     unsigned char* byteCode, int size)
 {
     DX11PixelShader* pixelShader
-        = new DX11PixelShader(d3d11Device, d3d11Context);
+        = new DX11PixelShader(d3d11Device, d3d11Context, deviceLock);
     pixelShader->setCompiledByteArray((unsigned char*)byteCode, size);
 
     pixelShader->createConstBuffer(sizeof(float) * 3,
@@ -1217,5 +1248,6 @@ DLLEXPORT ID3D11DeviceContext* DirectX11::zContext()
 
 DXBuffer* DirectX11::createStructuredBuffer(int eSize)
 {
-    return new DX11StructuredBuffer(eSize, d3d11Device, d3d11Context);
+    return new DX11StructuredBuffer(
+        eSize, d3d11Device, d3d11Context, deviceLock);
 }

+ 14 - 5
DXBuffer.cpp

@@ -71,8 +71,10 @@ int DXBuffer::getElementCount() const
 DX11Buffer::DX11Buffer(int eSize,
     ID3D11Device* device,
     ID3D11DeviceContext* context,
-    int bindFlags)
-    : DXBuffer(eSize)
+    int bindFlags,
+    Critical& deviceLock)
+    : DXBuffer(eSize),
+      deviceLock(deviceLock)
 {
     buffer = 0;
     description = new D3D11_BUFFER_DESC();
@@ -106,7 +108,9 @@ void DX11Buffer::copyToGPU(int byteCount)
     if (!buffer)
     {
         description->ByteWidth = len;
+        deviceLock.lock();
         device->CreateBuffer(description, 0, &buffer);
+        deviceLock.unlock();
         if (data) changed = 1;
     }
     if (changed)
@@ -142,12 +146,15 @@ ID3D11Buffer* DX11Buffer::zBuffer() const
 
 // Constructor
 // eSize: The length of an element in bytes
-DX11StructuredBuffer::DX11StructuredBuffer(
-    int eSize, ID3D11Device* device, ID3D11DeviceContext* context)
+DX11StructuredBuffer::DX11StructuredBuffer(int eSize,
+    ID3D11Device* device,
+    ID3D11DeviceContext* context,
+    Critical& deviceLock)
     : DX11Buffer(eSize,
           device,
           context,
-          D3D11_BIND_UNORDERED_ACCESS | D3D11_BIND_SHADER_RESOURCE)
+          D3D11_BIND_UNORDERED_ACCESS | D3D11_BIND_SHADER_RESOURCE,
+          deviceLock)
 {
     description->MiscFlags = D3D11_RESOURCE_MISC_BUFFER_STRUCTURED;
     description->StructureByteStride = eSize;
@@ -176,7 +183,9 @@ void DX11StructuredBuffer::copyToGPU(int byteCount)
         desc.Format = DXGI_FORMAT_UNKNOWN;
         desc.BufferEx.NumElements
             = description->ByteWidth / description->StructureByteStride;
+        deviceLock.lock();
         device->CreateShaderResourceView(buffer, &desc, &view);
+        deviceLock.unlock();
     }
 }
 

+ 8 - 3
DXBuffer.h

@@ -1,5 +1,6 @@
 #pragma once
 
+#include "Critical.h"
 #include "OperatingSystem.h"
 #include "ReferenceCounter.h"
 
@@ -59,6 +60,7 @@ namespace Framework
         ID3D11Buffer* buffer;
         ID3D11Device* device;
         ID3D11DeviceContext* context;
+        Critical& deviceLock;
 
     public:
         //! Constructor
@@ -66,7 +68,8 @@ namespace Framework
         DLLEXPORT DX11Buffer(int eSize,
             ID3D11Device* device,
             ID3D11DeviceContext* context,
-            int bindFlags);
+            int bindFlags,
+            Critical& deviceLock);
         //! Destructor
         DLLEXPORT virtual ~DX11Buffer();
         //! Copies the data into the buffer if it has changed
@@ -85,8 +88,10 @@ namespace Framework
     public:
         //! Constructor
         //! eSize: The length of an element in bytes
-        DLLEXPORT DX11StructuredBuffer(
-            int eSize, ID3D11Device* device, ID3D11DeviceContext* context);
+        DLLEXPORT DX11StructuredBuffer(int eSize,
+            ID3D11Device* device,
+            ID3D11DeviceContext* context,
+            Critical& deviceLock);
         //! Destructor
         DLLEXPORT virtual ~DX11StructuredBuffer();
         //! Copies the data into the buffer if it has changed

+ 153 - 163
Diagram.cpp

@@ -3,10 +3,10 @@
 #include <math.h>
 
 #include "AlphaField.h"
-#include "Image.h"
-#include "MouseEvent.h"
 #include "Border.h"
 #include "Font.h"
+#include "Image.h"
+#include "MouseEvent.h"
 #include "Scroll.h"
 #include "Text.h"
 #include "ToolTip.h"
@@ -106,8 +106,7 @@ void LiveLineDiagram::addPoint(int lNum, int x, int h) // adds a point
         {
             ph_tmp->remove(0);
             pb_tmp->remove(0);
-            if (!pb_tmp->getEntryCount() || !ph_tmp->getEntryCount())
-                break;
+            if (!pb_tmp->getEntryCount() || !ph_tmp->getEntryCount()) break;
             int ii = -i;
             i = pb_tmp->get(0);
             i -= ii;
@@ -134,12 +133,12 @@ void LiveLineDiagram::render(Image& zRObj) // draws to zRObj
 {
     if (hasStyle(Style::Visible))
     {
-        lockDrawable();
+        rwLock.lockRead();
         removeStyle(Style::VScroll | Style::HScroll);
         DrawableBackground::render(zRObj);
         if (!zRObj.setDrawOptions(innenPosition, innenSize))
         {
-            unlockDrawable();
+            rwLock.unlockRead();
             return;
         }
         int hv = getHighestValue();
@@ -207,7 +206,7 @@ void LiveLineDiagram::render(Image& zRObj) // draws to zRObj
             }
         }
         zRObj.releaseDrawOptions();
-        unlockDrawable();
+        rwLock.unlockRead();
     }
 }
 
@@ -233,7 +232,8 @@ int LiveLineDiagram::getGColor() const // returns the grid color
     return gF;
 }
 
-int LiveLineDiagram::getLineNumber(const char* name) const // returns the line number
+int LiveLineDiagram::getLineNumber(
+    const char* name) const // returns the line number
 {
     for (int i = 0; i < lines; ++i)
     {
@@ -367,7 +367,7 @@ DiagramData::~DiagramData()
 
 // Contents of the BaseDiagram class from Diagram.h
 // Constructor
-BaseDiagram::BaseDiagram(Critical* lock)
+BaseDiagram::BaseDiagram(ReadWriteLock* lock)
     : daten(new DiagramData()),
       changed(0),
       lock(lock)
@@ -383,16 +383,16 @@ BaseDiagram::~BaseDiagram()
 void BaseDiagram::setDiagramDataZ(
     DiagramData* dd) // Sets a pointer to the diagram data
 {
-    lock->lock();
+    lock->lockWrite();
     if (daten) daten->release();
     daten = dd;
-    lock->unlock();
+    lock->unlockWrite();
     changed = 1;
 }
 
 void BaseDiagram::setDiagramData(DiagramData* dd) // copies the diagram data
 {
-    lock->lock();
+    lock->lockWrite();
     if (!daten) daten = new DiagramData();
     daten->style = dd->style;
     daten->gridWidth = dd->gridWidth;
@@ -442,122 +442,122 @@ void BaseDiagram::setDiagramData(DiagramData* dd) // copies the diagram data
         }
     }
     dd->release();
-    lock->unlock();
+    lock->unlockWrite();
     changed = 1;
 }
 
 void BaseDiagram::setGridThickness(int d) // set raster thickness
 {
-    lock->lock();
+    lock->lockWrite();
     if (!daten) daten = new DiagramData();
     if (daten->rasterDicke != d) changed = 1;
     daten->rasterDicke = d;
-    lock->unlock();
+    lock->unlockWrite();
 }
 
 void BaseDiagram::setGridWidth(int br) // set raster width
 {
-    lock->lock();
+    lock->lockWrite();
     if (!daten) daten = new DiagramData();
     if (daten->gridWidth != br) changed = 1;
     daten->gridWidth = br;
-    lock->unlock();
+    lock->unlockWrite();
 }
 
 void BaseDiagram::setGridHeight(int hi) // set raster height
 {
-    lock->lock();
+    lock->lockWrite();
     if (!daten) daten = new DiagramData();
     if (daten->rasterHeight != hi) changed = 1;
     daten->rasterHeight = hi;
-    lock->unlock();
+    lock->unlockWrite();
 }
 
 void BaseDiagram::setGridColor(int f) // set raster color
 {
-    lock->lock();
+    lock->lockWrite();
     if (!daten) daten = new DiagramData();
     if (daten->rasterColor != f) changed = 1;
     daten->rasterColor = f;
-    lock->unlock();
+    lock->unlockWrite();
 }
 
 void BaseDiagram::setHIntervalWidth(double br) // interval width
 {
-    lock->lock();
+    lock->lockWrite();
     if (!daten) daten = new DiagramData();
     daten->hIntervalWidth = br;
-    lock->unlock();
+    lock->unlockWrite();
 }
 
 void BaseDiagram::setVIntervalHeight(double hi) // interval height
 {
-    lock->lock();
+    lock->lockWrite();
     if (!daten) daten = new DiagramData();
     daten->vIntervalHeight = hi;
-    lock->unlock();
+    lock->unlockWrite();
 }
 
 void BaseDiagram::setHIntervalColor(int f) // color of the horizontal interval
 {
-    lock->lock();
+    lock->lockWrite();
     if (!daten) daten = new DiagramData();
     if (daten->hIntervalColor != f) changed = 1;
     daten->hIntervalColor = f;
-    lock->unlock();
+    lock->unlockWrite();
 }
 
 void BaseDiagram::setVIntervalColor(int f) // color of the vertical interval
 {
-    lock->lock();
+    lock->lockWrite();
     if (!daten) daten = new DiagramData();
     if (daten->vIntervalColor != f) changed = 1;
     daten->vIntervalColor = f;
-    lock->unlock();
+    lock->unlockWrite();
 }
 
 void BaseDiagram::setHIntervalName(
     const char* name) // Sets the name of the horizontal interval
 {
-    lock->lock();
+    lock->lockWrite();
     if (!daten) daten = new DiagramData();
     if (!daten->hIntervalName) daten->hIntervalName = new Text();
     if (!daten->hIntervalName->isEqual(name)) changed = 1;
     daten->hIntervalName->setText(name);
-    lock->unlock();
+    lock->unlockWrite();
 }
 
 void BaseDiagram::setHIntervalName(Text* name)
 {
-    lock->lock();
+    lock->lockWrite();
     if (!daten) daten = new DiagramData();
     if (!daten->hIntervalName) daten->hIntervalName = new Text();
     if (!daten->hIntervalName->isEqual(*name)) changed = 1;
     daten->hIntervalName->setText(*name);
     name->release();
-    lock->unlock();
+    lock->unlockWrite();
 }
 
 void BaseDiagram::setVIntervalName(
     const char* name) // Sets the name of the vertical interval
 {
-    lock->lock();
+    lock->lockWrite();
     if (!daten) daten = new DiagramData();
     if (!daten->vIntervalName) daten->vIntervalName = new Text();
     if (!daten->vIntervalName->isEqual(name)) changed = 1;
     daten->vIntervalName->setText(name);
-    lock->unlock();
+    lock->unlockWrite();
 }
 
 void BaseDiagram::setVIntervalName(Text* name)
 {
-    lock->lock();
+    lock->lockWrite();
     if (!daten) daten = new DiagramData();
     if (!daten->vIntervalName) daten->vIntervalName = new Text();
     if (!daten->vIntervalName->isEqual(*name)) changed = 1;
     daten->vIntervalName->setText(*name);
     name->release();
-    lock->unlock();
+    lock->unlockWrite();
 }
 
 void BaseDiagram::addHIntervalText(double hInterval,
@@ -575,7 +575,7 @@ void BaseDiagram::addHIntervalText(double hInterval, Text* text)
 void BaseDiagram::setHIntervalTextZ(double hInterval,
     Text* text) // Sets the text of a horizontal interval
 {
-    lock->lock();
+    lock->lockWrite();
     if (!daten) daten = new DiagramData();
     if (!daten->hIntervalWerte) daten->hIntervalWerte = new Array<double>();
     if (!daten->hIntervalTexte) daten->hIntervalTexte = new RCArray<Text>();
@@ -586,14 +586,14 @@ void BaseDiagram::setHIntervalTextZ(double hInterval,
             && daten->hIntervalWerte->get(i) == hInterval)
         {
             daten->hIntervalTexte->set(text, i);
-            lock->unlock();
+            lock->unlockWrite();
             changed = 1;
             return;
         }
     }
     daten->hIntervalWerte->set(hInterval, anz);
     daten->hIntervalTexte->set(text, anz);
-    lock->unlock();
+    lock->unlockWrite();
     changed = 1;
 }
 
@@ -605,7 +605,7 @@ void BaseDiagram::setHIntervalText(double hInterval, Text* text)
 
 void BaseDiagram::setHIntervalText(double hInterval, const char* text)
 {
-    lock->lock();
+    lock->lockWrite();
     if (!daten) daten = new DiagramData();
     if (!daten->hIntervalWerte) daten->hIntervalWerte = new Array<double>();
     if (!daten->hIntervalTexte) daten->hIntervalTexte = new RCArray<Text>();
@@ -619,21 +619,21 @@ void BaseDiagram::setHIntervalText(double hInterval, const char* text)
                 daten->hIntervalTexte->set(new Text(text), i);
             else
                 daten->hIntervalTexte->z(i)->setText(text);
-            lock->unlock();
+            lock->unlockWrite();
             changed = 1;
             return;
         }
     }
     daten->hIntervalWerte->set(hInterval, anz);
     daten->hIntervalTexte->set(new Text(text), anz);
-    lock->unlock();
+    lock->unlockWrite();
     changed = 1;
 }
 
 void BaseDiagram::removeHIntervalText(
     double hInterval) // removes the text of a horizontal interval
 {
-    lock->lock();
+    lock->lockWrite();
     if (!daten) daten = new DiagramData();
     if (!daten->hIntervalWerte) daten->hIntervalWerte = new Array<double>();
     if (!daten->hIntervalTexte) daten->hIntervalTexte = new RCArray<Text>();
@@ -645,12 +645,12 @@ void BaseDiagram::removeHIntervalText(
         {
             daten->hIntervalTexte->remove(i);
             daten->hIntervalWerte->remove(i);
-            lock->unlock();
+            lock->unlockWrite();
             changed = 1;
             return;
         }
     }
-    lock->unlock();
+    lock->unlockWrite();
 }
 
 void BaseDiagram::addVIntervalText(double vInterval,
@@ -668,7 +668,7 @@ void BaseDiagram::addVIntervalText(double vInterval, Text* text)
 void BaseDiagram::setVIntervalTextZ(
     double vInterval, Text* text) // Sets the text of a vertical interval
 {
-    lock->lock();
+    lock->lockWrite();
     if (!daten) daten = new DiagramData();
     if (!daten->vIntervalWerte) daten->vIntervalWerte = new Array<double>();
     if (!daten->vIntervalTexte) daten->vIntervalTexte = new RCArray<Text>();
@@ -679,14 +679,14 @@ void BaseDiagram::setVIntervalTextZ(
             && daten->vIntervalWerte->get(i) == vInterval)
         {
             daten->vIntervalTexte->set(text, i);
-            lock->unlock();
+            lock->unlockWrite();
             changed = 1;
             return;
         }
     }
     daten->vIntervalWerte->set(vInterval, anz);
     daten->vIntervalTexte->set(text, anz);
-    lock->unlock();
+    lock->unlockWrite();
     changed = 1;
 }
 
@@ -698,7 +698,7 @@ void BaseDiagram::setVIntervalText(double vInterval, Text* text)
 
 void BaseDiagram::setVIntervalText(double vInterval, const char* text)
 {
-    lock->lock();
+    lock->lockWrite();
     if (!daten) daten = new DiagramData();
     if (!daten->vIntervalWerte) daten->vIntervalWerte = new Array<double>();
     if (!daten->vIntervalTexte) daten->vIntervalTexte = new RCArray<Text>();
@@ -712,21 +712,21 @@ void BaseDiagram::setVIntervalText(double vInterval, const char* text)
                 daten->vIntervalTexte->set(new Text(text), i);
             else
                 daten->vIntervalTexte->z(i)->setText(text);
-            lock->unlock();
+            lock->unlockWrite();
             changed = 1;
             return;
         }
     }
     daten->vIntervalWerte->set(vInterval, anz);
     daten->vIntervalTexte->set(new Text(text), anz);
-    lock->unlock();
+    lock->unlockWrite();
     changed = 1;
 }
 
 void BaseDiagram::removeVIntervalText(
     double vInterval) // removes the text of a vertical interval
 {
-    lock->lock();
+    lock->lockWrite();
     if (!daten) daten = new DiagramData();
     if (!daten->vIntervalWerte) daten->vIntervalWerte = new Array<double>();
     if (!daten->vIntervalTexte) daten->vIntervalTexte = new RCArray<Text>();
@@ -738,27 +738,27 @@ void BaseDiagram::removeVIntervalText(
         {
             daten->vIntervalTexte->remove(i);
             daten->vIntervalWerte->remove(i);
-            lock->unlock();
+            lock->unlockWrite();
             changed = 1;
             return;
         }
     }
-    lock->unlock();
+    lock->unlockWrite();
 }
 
 void BaseDiagram::addValueZ(DiagramValue* w) // Adds a value
 {
-    lock->lock();
+    lock->lockWrite();
     if (!daten) daten = new DiagramData();
     if (!daten->werte) daten->werte = new RCArray<DiagramValue>();
     daten->werte->add(w);
-    lock->unlock();
+    lock->unlockWrite();
     changed = 1;
 }
 
 void BaseDiagram::addValue(DiagramValue* w)
 {
-    lock->lock();
+    lock->lockWrite();
     DiagramValue* tmp = new DiagramValue();
     tmp->style = w->style;
     tmp->color = w->color;
@@ -777,19 +777,19 @@ void BaseDiagram::addValue(DiagramValue* w)
     }
     w->release();
     addValueZ(tmp);
-    lock->unlock();
+    lock->unlockWrite();
     changed = 1;
 }
 
 void BaseDiagram::addValue(const char* name)
 {
-    lock->lock();
+    lock->lockWrite();
     if (!daten) daten = new DiagramData();
     if (!daten->werte) daten->werte = new RCArray<DiagramValue>();
     DiagramValue* w = new DiagramValue();
     w->name->setText(name);
     daten->werte->add(w);
-    lock->unlock();
+    lock->unlockWrite();
     changed = 1;
 }
 
@@ -802,19 +802,20 @@ void BaseDiagram::addValue(Text* txt)
 void BaseDiagram::setValueColor(int wNum, int f) // sets the color of a value
 {
     if (wNum < 0) return;
-    lock->lock();
+    lock->lockWrite();
     if (!daten) daten = new DiagramData();
     if (!daten->werte) daten->werte = new RCArray<DiagramValue>();
     if (!daten->werte->z(wNum)) daten->werte->set(new DiagramValue(), wNum);
     daten->werte->z(wNum)->color = f;
-    lock->unlock();
+    lock->unlockWrite();
     changed = 1;
 }
 
-void BaseDiagram::addPointZ(int wNum, DiagramPoint* p) // adds a point to a value
+void BaseDiagram::addPointZ(
+    int wNum, DiagramPoint* p) // adds a point to a value
 {
     if (wNum < 0) return;
-    lock->lock();
+    lock->lockWrite();
     if (!daten) daten = new DiagramData();
     if (!daten->werte) daten->werte = new RCArray<DiagramValue>();
     while (!daten->werte->has(wNum))
@@ -822,14 +823,14 @@ void BaseDiagram::addPointZ(int wNum, DiagramPoint* p) // adds a point to a valu
     if (!daten->werte->z(wNum)->punkte)
         daten->werte->z(wNum)->punkte = new Array<DiagramPoint*>();
     daten->werte->z(wNum)->punkte->add(p);
-    lock->unlock();
+    lock->unlockWrite();
     changed = 1;
 }
 
 void BaseDiagram::addPoint(int wNum, DiagramPoint* p)
 {
     if (wNum < 0) return;
-    lock->lock();
+    lock->lockWrite();
     if (!daten) daten = new DiagramData();
     if (!daten->werte) daten->werte = new RCArray<DiagramValue>();
     while (!daten->werte->has(wNum))
@@ -840,14 +841,14 @@ void BaseDiagram::addPoint(int wNum, DiagramPoint* p)
     tmp->hInterval = p->hInterval;
     tmp->vInterval = p->vInterval;
     daten->werte->z(wNum)->punkte->add(tmp);
-    lock->unlock();
+    lock->unlockWrite();
     changed = 1;
 }
 
 void BaseDiagram::addPoint(int wNum, double hI, double vI)
 {
     if (wNum < 0) return;
-    lock->lock();
+    lock->lockWrite();
     if (!daten) daten = new DiagramData();
     if (!daten->werte) daten->werte = new RCArray<DiagramValue>();
     if (!daten->werte->z(wNum)) daten->werte->set(new DiagramValue(), wNum);
@@ -857,7 +858,7 @@ void BaseDiagram::addPoint(int wNum, double hI, double vI)
     tmp->hInterval = hI;
     tmp->vInterval = vI;
     daten->werte->z(wNum)->punkte->add(tmp);
-    lock->unlock();
+    lock->unlockWrite();
     changed = 1;
 }
 
@@ -880,7 +881,7 @@ void BaseDiagram::setPoint(int wNum, double hI, double h, double v)
 void BaseDiagram::setPointZ(int wNum, int pNum, DiagramPoint* p)
 {
     if (pNum < 0 || wNum < 0) return;
-    lock->lock();
+    lock->lockWrite();
     if (!daten) daten = new DiagramData();
     if (!daten->werte) daten->werte = new RCArray<DiagramValue>();
     if (!daten->werte->z(wNum)) daten->werte->set(new DiagramValue(), wNum);
@@ -889,7 +890,7 @@ void BaseDiagram::setPointZ(int wNum, int pNum, DiagramPoint* p)
     if (daten->werte->z(wNum)->punkte->has(pNum))
         delete daten->werte->z(wNum)->punkte->get(pNum);
     daten->werte->z(wNum)->punkte->set(p, pNum);
-    lock->unlock();
+    lock->unlockWrite();
     changed = 1;
 }
 
@@ -902,7 +903,7 @@ void BaseDiagram::setPoint(int wNum, int pNum, DiagramPoint* p)
 void BaseDiagram::setPoint(int wNum, int pNum, double h, double v)
 {
     if (pNum < 0 || wNum < 0) return;
-    lock->lock();
+    lock->lockWrite();
     if (!daten) daten = new DiagramData();
     if (!daten->werte) daten->werte = new RCArray<DiagramValue>();
     if (!daten->werte->z(wNum)) daten->werte->set(new DiagramValue(), wNum);
@@ -912,14 +913,14 @@ void BaseDiagram::setPoint(int wNum, int pNum, double h, double v)
         daten->werte->z(wNum)->punkte->set(new DiagramPoint(), pNum);
     daten->werte->z(wNum)->punkte->get(pNum)->hInterval = h;
     daten->werte->z(wNum)->punkte->get(pNum)->vInterval = v;
-    lock->unlock();
+    lock->unlockWrite();
     changed = 1;
 }
 
 // Deletes an existing point
 void BaseDiagram::removePoint(int wNum, double hI)
 {
-    lock->lock();
+    lock->lockWrite();
     if (!daten) daten = new DiagramData();
     if (!daten->werte) daten->werte = new RCArray<DiagramValue>();
     if (!daten->werte->z(wNum)) daten->werte->set(new DiagramValue(), wNum);
@@ -933,17 +934,17 @@ void BaseDiagram::removePoint(int wNum, double hI)
         {
             delete daten->werte->z(wNum)->punkte->get(i);
             daten->werte->z(wNum)->punkte->remove(i);
-            lock->unlock();
+            lock->unlockWrite();
             changed = 1;
             return;
         }
     }
-    lock->unlock();
+    lock->unlockWrite();
 }
 
 void BaseDiagram::removePoint(int wNum, int pNum)
 {
-    lock->lock();
+    lock->lockWrite();
     if (!daten) daten = new DiagramData();
     if (!daten->werte) daten->werte = new RCArray<DiagramValue>();
     if (!daten->werte->z(wNum)) daten->werte->set(new DiagramValue(), wNum);
@@ -955,22 +956,22 @@ void BaseDiagram::removePoint(int wNum, int pNum)
         daten->werte->z(wNum)->punkte->remove(pNum);
         changed = 1;
     }
-    lock->unlock();
+    lock->unlockWrite();
 }
 
 void BaseDiagram::removeValue(int wNum) // removes a value
 {
-    lock->lock();
+    lock->lockWrite();
     if (!daten) daten = new DiagramData();
     if (!daten->werte) daten->werte = new RCArray<DiagramValue>();
     daten->werte->remove(wNum);
-    lock->unlock();
+    lock->unlockWrite();
     changed = 1;
 }
 
 void BaseDiagram::removeValue(const char* name)
 {
-    lock->lock();
+    lock->lockWrite();
     if (!daten) daten = new DiagramData();
     if (!daten->werte) daten->werte = new RCArray<DiagramValue>();
     int anz = daten->werte->getEntryCount();
@@ -980,12 +981,12 @@ void BaseDiagram::removeValue(const char* name)
         if (tmp && tmp->name && tmp->name->isEqual(name))
         {
             daten->werte->remove(i);
-            lock->unlock();
+            lock->unlockWrite();
             changed = 1;
             return;
         }
     }
-    lock->unlock();
+    lock->unlockWrite();
 }
 
 void BaseDiagram::removeValue(Text* name)
@@ -1023,7 +1024,8 @@ void BaseDiagram::removeDataStyle(int style)
     daten->style &= ~style;
 }
 
-void BaseDiagram::addValueStyle(int wNum, int style) // Sets the style of a value
+void BaseDiagram::addValueStyle(
+    int wNum, int style) // Sets the style of a value
 {
     if (wNum < 0) return;
     if (!daten) daten = new DiagramData();
@@ -1072,7 +1074,8 @@ DiagramData* BaseDiagram::zDiagramData() const
     return daten;
 }
 
-DiagramValue* BaseDiagram::getDiagramValue(int wNum) const // Returns the data of a value
+DiagramValue* BaseDiagram::getDiagramValue(
+    int wNum) const // Returns the data of a value
 {
     return (daten && daten->werte) ? daten->werte->get(wNum) : 0;
 }
@@ -1158,7 +1161,7 @@ bool BaseDiagram::hasValueStyleNot(int wNum, int style) const
 // Constructor
 LineDiagram::LineDiagram()
     : DrawableBackground(),
-      BaseDiagram(&cs),
+      BaseDiagram(&rwLock),
       textRd(0),
       dRam(new LBorder()),
       dBgF(0),
@@ -1168,7 +1171,7 @@ LineDiagram::LineDiagram()
       hIntervalRB(new Image()),
       fontGr(12)
 {
-    style = Style::MELockDrawable;
+    style = 0;
     vertikalScrollBar = new VScrollBar();
     horizontalScrollBar = new HScrollBar();
 }
@@ -1211,68 +1214,68 @@ void LineDiagram::doMouseEvent(MouseEvent& me, bool userRet)
 // non-constant
 void LineDiagram::setTextRendererZ(TextRenderer* textRd)
 {
-    lockDrawable();
+    rwLock.lockWrite();
     if (this->textRd) this->textRd->release();
     this->textRd = textRd;
-    unlockDrawable();
+    rwLock.unlockWrite();
 }
 
 void LineDiagram::setFontZ(Font* font) // Sets the font
 {
-    lockDrawable();
+    rwLock.lockWrite();
     if (!this->textRd)
         textRd = new TextRenderer(font);
     else
         textRd->setFontZ(font);
     rend = 1;
-    unlockDrawable();
+    rwLock.unlockWrite();
 }
 
 void LineDiagram::setFontSize(int gr)
 {
-    lockDrawable();
+    rwLock.lockWrite();
     if (fontGr != gr) rend = 1;
     fontGr = gr;
-    unlockDrawable();
+    rwLock.unlockWrite();
 }
 
 void LineDiagram::setDataBorderZ(
     Border* ram) // Sets the inner border around the actual diagram
 {
-    lockDrawable();
+    rwLock.lockWrite();
     if (dRam) dRam->release();
     dRam = ram;
-    unlockDrawable();
+    rwLock.unlockWrite();
     rend = 1;
 }
 
 void LineDiagram::setDataBorder(Border* ram)
 {
-    lockDrawable();
+    rwLock.lockWrite();
     if (!dRam) dRam = new LBorder();
     dRam->setAlpha(ram->hasAlpha());
     dRam->setColor(ram->getColor());
     dRam->setBorderWidth(ram->getRWidth());
-    unlockDrawable();
+    rwLock.unlockWrite();
     ram->release();
     rend = 1;
 }
 
 void LineDiagram::setDataBorderWidth(int br)
 {
-    lockDrawable();
+    rwLock.lockWrite();
     if (!dRam) dRam = new LBorder();
     if (dRam->getRWidth() != br) rend = 1;
     dRam->setBorderWidth(br);
-    unlockDrawable();
+    rwLock.unlockWrite();
 }
 
 void LineDiagram::setDataBorderColor(int f)
 {
-    lockDrawable();
+    rwLock.lockWrite();
     if (!dRam) dRam = new LBorder();
     dRam->setColor(f);
-    unlockDrawable();
+    rwLock.unlockWrite();
     rend = 1;
 }
 
@@ -1285,20 +1288,20 @@ void LineDiagram::setDataBackgroundColor(
 
 void LineDiagram::setDataBackgroundImageZ(Image* b)
 {
-    lockDrawable();
+    rwLock.lockWrite();
     if (dBgB) dBgB->release();
     dBgB = b;
-    unlockDrawable();
+    rwLock.unlockWrite();
     rend = 1;
 }
 
 void LineDiagram::setDataBackgroundImage(Image* b)
 {
-    lockDrawable();
+    rwLock.lockWrite();
     if (!dBgB) dBgB = new Image();
     dBgB->newImage(b->getWidth(), b->getHeight(), 0);
     dBgB->drawImage(0, 0, b->getWidth(), b->getHeight(), *b);
-    unlockDrawable();
+    rwLock.unlockWrite();
     b->release();
     rend = 1;
 }
@@ -1306,40 +1309,40 @@ void LineDiagram::setDataBackgroundImage(Image* b)
 void LineDiagram::setDataAlphaFieldZ(
     AlphaField* af) // Sets the AlphaField of the actual diagram
 {
-    lockDrawable();
+    rwLock.lockWrite();
     if (dAf) dAf->release();
     dAf = af;
-    unlockDrawable();
+    rwLock.unlockWrite();
     rend = 1;
 }
 
 void LineDiagram::setDataAlphaField(AlphaField* af)
 {
-    lockDrawable();
+    rwLock.lockWrite();
     if (!dAf) dAf = new AlphaField();
     dAf->setColor(af->getColor());
     dAf->setStrength(af->getStrength());
-    unlockDrawable();
+    rwLock.unlockWrite();
     af->release();
     rend = 1;
 }
 
 void LineDiagram::setDataAlphaFieldColor(int f)
 {
-    lockDrawable();
+    rwLock.lockWrite();
     if (!dAf) dAf = new AlphaField();
     dAf->setColor(f);
-    unlockDrawable();
+    rwLock.unlockWrite();
     rend = 1;
 }
 
 void LineDiagram::setDataAlphaFieldStrength(int st)
 {
-    lockDrawable();
+    rwLock.lockWrite();
     if (!dAf) dAf = new AlphaField();
     if (dAf->getStrength() != st) rend = 1;
     dAf->setStrength(st);
-    unlockDrawable();
+    rwLock.unlockWrite();
 }
 
 void LineDiagram::render(Image& zRObj)
@@ -1347,7 +1350,7 @@ void LineDiagram::render(Image& zRObj)
     if (!hasDataStyle(DiagramData::Style::Visible)) return;
     DrawableBackground::render(zRObj);
     if (!zRObj.setDrawOptions(innenPosition, innenSize)) return;
-    lockDrawable();
+    rwLock.lockRead();
     int dgy = 0;
     int dgbr = innenSize.x;
     int dghi = innenSize.y;
@@ -1355,12 +1358,10 @@ void LineDiagram::render(Image& zRObj)
     int hIAnz = 0;
     if (daten)
     { // calculating auto values
-        vIAnz = daten->vIntervalWerte
-                  ? daten->vIntervalWerte->getEntryCount()
-                  : 0;
-        hIAnz = daten->hIntervalWerte
-                  ? daten->hIntervalWerte->getEntryCount()
-                  : 0;
+        vIAnz = daten->vIntervalWerte ? daten->vIntervalWerte->getEntryCount()
+                                      : 0;
+        hIAnz = daten->hIntervalWerte ? daten->hIntervalWerte->getEntryCount()
+                                      : 0;
         if (daten->vIntervalWerte
             && hasDataStyle(DiagramData::Style::AutoIntervalHeight))
         {
@@ -1413,8 +1414,7 @@ void LineDiagram::render(Image& zRObj)
                 || vIntervalRB->getHeight() != fontGr + 2)
                 vIntervalRB->newImage(vIRBbr, fontGr + 2, 0xFF000000);
             else
-                vIntervalRB->fillRegion(
-                    0, 0, vIRBbr, fontGr + 2, 0xFF000000);
+                vIntervalRB->fillRegion(0, 0, vIRBbr, fontGr + 2, 0xFF000000);
             textRd->setFontSize(fontGr);
             if (daten->vIntervalWerte)
             {
@@ -1453,8 +1453,7 @@ void LineDiagram::render(Image& zRObj)
                         && daten->vIntervalTexte
                         && daten->vIntervalTexte->z(rf[i]))
                         txt = daten->vIntervalTexte->z(rf[i])->getText();
-                    else if (hasDataStyleNot(
-                                 DiagramData::Style::VIntervalTexte)
+                    else if (hasDataStyleNot(DiagramData::Style::VIntervalTexte)
                              || !daten->vIntervalWerte)
                         txt = daten->vIntervalWerte->get(rf[i]);
                     xPos = (int)(daten->vIntervalWerte->get(rf[i])
@@ -1471,11 +1470,8 @@ void LineDiagram::render(Image& zRObj)
                         xPos = vIntervalRB->getWidth() - br;
                     if (xPos >= rWeite + 10)
                     {
-                        textRd->renderText(xPos,
-                            1,
-                            txt,
-                            *vIntervalRB,
-                            daten->vIntervalColor);
+                        textRd->renderText(
+                            xPos, 1, txt, *vIntervalRB, daten->vIntervalColor);
                         rWeite = xPos + br + 10;
                     }
                 }
@@ -1523,8 +1519,7 @@ void LineDiagram::render(Image& zRObj)
                 || hIntervalRB->getHeight() != fontGr + 2)
                 hIntervalRB->newImage(hIRBbr, fontGr + 2, 0xFF000000);
             else
-                hIntervalRB->fillRegion(
-                    0, 0, hIRBbr, fontGr + 2, 0xFF000000);
+                hIntervalRB->fillRegion(0, 0, hIRBbr, fontGr + 2, 0xFF000000);
             textRd->setFontSize(fontGr);
             if (daten->hIntervalWerte)
             {
@@ -1563,8 +1558,7 @@ void LineDiagram::render(Image& zRObj)
                         && daten->hIntervalTexte
                         && daten->hIntervalTexte->z(rf[i]))
                         txt = daten->hIntervalTexte->z(rf[i])->getText();
-                    else if (hasDataStyleNot(
-                                 DiagramData::Style::HIntervalTexte)
+                    else if (hasDataStyleNot(DiagramData::Style::HIntervalTexte)
                              || !daten->hIntervalWerte)
                         txt = daten->hIntervalWerte->get(rf[i]);
                     xPos = (int)(daten->hIntervalWerte->get(rf[i])
@@ -1577,11 +1571,8 @@ void LineDiagram::render(Image& zRObj)
                         xPos = hIntervalRB->getWidth() - br;
                     if (xPos >= rWeite + 10)
                     {
-                        textRd->renderText(xPos,
-                            1,
-                            txt,
-                            *hIntervalRB,
-                            daten->hIntervalColor);
+                        textRd->renderText(
+                            xPos, 1, txt, *hIntervalRB, daten->hIntervalColor);
                         rWeite = xPos + br + 10;
                     }
                 }
@@ -1612,7 +1603,7 @@ void LineDiagram::render(Image& zRObj)
     if (!zRObj.setDrawOptions(0, dgy, dgbr, dghi))
     {
         zRObj.releaseDrawOptions();
-        unlockDrawable();
+        rwLock.unlockRead();
         return;
     }
     dgy = 0;
@@ -1627,7 +1618,7 @@ void LineDiagram::render(Image& zRObj)
     {
         zRObj.releaseDrawOptions();
         zRObj.releaseDrawOptions();
-        unlockDrawable();
+        rwLock.unlockRead();
         return;
     }
     if (hasStyle(Style::DataBackground))
@@ -1642,7 +1633,8 @@ void LineDiagram::render(Image& zRObj)
                 zRObj.alphaImage(
                     0, 0, dgbr - dgrbr * 2, dghi - dgrbr * 2, *dBgB);
             else
-                zRObj.drawImage(0, 0, dgbr - dgrbr * 2, dghi - dgrbr * 2, *dBgB);
+                zRObj.drawImage(
+                    0, 0, dgbr - dgrbr * 2, dghi - dgrbr * 2, *dBgB);
         }
     }
     if (hasStyle(Style::DataBuffered) && dAf)
@@ -1776,7 +1768,8 @@ void LineDiagram::render(Image& zRObj)
                                 double y = (double)ay;
                                 ax = ax < 0 ? 0 : ax;
                                 bx = bx > dgbr - dgrbr ? dgbr - dgrbr : bx;
-                                if (hasValueStyle(i, DiagramValue::Style::HAlpha))
+                                if (hasValueStyle(
+                                        i, DiagramValue::Style::HAlpha))
                                 {
                                     for (int x = ax; x < bx; x++, y += yf)
                                         zRObj.drawLineVAlpha(x,
@@ -1792,7 +1785,8 @@ void LineDiagram::render(Image& zRObj)
                                             dgmhi - (int)(y + 0.5),
                                             wert->background);
                                 }
-                                if (hasValueStyle(i, DiagramValue::Style::Alpha))
+                                if (hasValueStyle(
+                                        i, DiagramValue::Style::Alpha))
                                     zRObj.drawLineAlpha(Point(ax, ay),
                                         Point(bx, by),
                                         wert->color);
@@ -1816,34 +1810,30 @@ void LineDiagram::render(Image& zRObj)
                         {
                             if (hasValueStyle(i, DiagramValue::Style::Alpha))
                                 zRObj.drawLineAlpha(
-                                    Point(
-                                        (int)(rpx
-                                              + vorher->hInterval
-                                                    * daten->hIntervalWidth),
+                                    Point((int)(rpx
+                                                + vorher->hInterval
+                                                      * daten->hIntervalWidth),
                                         (int)(dgmhi
                                               - vorher->vInterval
                                                     * daten->vIntervalHeight)),
-                                    Point(
-                                        (int)(rpx
-                                              + jetzt->hInterval
-                                                    * daten->hIntervalWidth),
+                                    Point((int)(rpx
+                                                + jetzt->hInterval
+                                                      * daten->hIntervalWidth),
                                         (int)(dgmhi
                                               - jetzt->vInterval
                                                     * daten->vIntervalHeight)),
                                     wert->color);
                             else
                                 zRObj.drawLine(
-                                    Point(
-                                        (int)(rpx
-                                              + vorher->hInterval
-                                                    * daten->hIntervalWidth),
+                                    Point((int)(rpx
+                                                + vorher->hInterval
+                                                      * daten->hIntervalWidth),
                                         (int)(dgmhi
                                               - vorher->vInterval
                                                     * daten->vIntervalHeight)),
-                                    Point(
-                                        (int)(rpx
-                                              + jetzt->hInterval
-                                                    * daten->hIntervalWidth),
+                                    Point((int)(rpx
+                                                + jetzt->hInterval
+                                                      * daten->hIntervalWidth),
                                         (int)(dgmhi
                                               - jetzt->vInterval
                                                     * daten->vIntervalHeight)),
@@ -1879,7 +1869,7 @@ void LineDiagram::render(Image& zRObj)
     zRObj.releaseDrawOptions();
     zRObj.releaseDrawOptions();
     zRObj.releaseDrawOptions();
-    unlockDrawable();
+    rwLock.unlockRead();
 }
 
 // constant
@@ -1930,8 +1920,8 @@ Image* LineDiagram::zDataBackgroundImage() const
     return dBgB;
 }
 
-AlphaField*
-LineDiagram::getDataAlphaField() const // Returns the AlphaField of the actual diagram
+AlphaField* LineDiagram::getDataAlphaField()
+    const // Returns the AlphaField of the actual diagram
 {
     return dAf ? dynamic_cast<AlphaField*>(dAf->getThis()) : 0;
 }

+ 25 - 23
Diagram.h

@@ -7,14 +7,14 @@
 
 namespace Framework
 {
-    class Border;     //! Border.h
-    class AlphaField;  //! AlphaField.h
-    class Text;       //! Text.h
-    class Font;    //! Font.h
-    class HScrollBar; //! Scroll.h
-    class VScrollBar; //! Scroll.h
-    class LiveLineDiagram;     //! from this file
-    class LineDiagram;      //! from this file
+    class Border;          //! Border.h
+    class AlphaField;      //! AlphaField.h
+    class Text;            //! Text.h
+    class Font;            //! Font.h
+    class HScrollBar;      //! Scroll.h
+    class VScrollBar;      //! Scroll.h
+    class LiveLineDiagram; //! from this file
+    class LineDiagram;     //! from this file
     class TextRenderer;
 
     //! A 2D GUI Framework drawing that draws a live diagram of values
@@ -81,7 +81,8 @@ namespace Framework
         //! to the left so that the new point appears on the right. If a point
         //! goes off the left edge of the diagram, it is deleted. This way the
         //! diagram appears like a live measurement \param x The distance to the
-        //! last point in pixels \param y The value of the displayed function at the point
+        //! last point in pixels \param y The value of the displayed function at
+        //! the point
         DLLEXPORT void addPoint(int lNum, int x, int h);
         //! Removes a graph
         //! \param lNum The index of the graph
@@ -187,12 +188,12 @@ namespace Framework
                 = 0x0004; //! Determines whether alpha blending should be used
                           //! for drawing the grid
             static const int AutoIntervalHeight
-                = 0x0008; //! Determines that all values are automatically scaled
-                          //! on the y axis so that the full height of the
-                          //! diagram is always used
+                = 0x0008; //! Determines that all values are automatically
+                          //! scaled on the y axis so that the full height of
+                          //! the diagram is always used
             static const int AutoIntervalWidth
-                = 0x0010; //! Determines that all values are automatically scaled
-                          //! on the x axis so that the full width of the
+                = 0x0010; //! Determines that all values are automatically
+                          //! scaled on the x axis so that the full width of the
                           //! diagram is always used
             static const int HInterval
                 = 0x0020; //! Determines whether the X axis should be drawn
@@ -212,12 +213,11 @@ namespace Framework
                           //! grid lines should be chosen automatically
 
             static const int intervale
-                = HInterval
-                | VInterval; //! Combines flags HInterval, VInterval
+                = HInterval | VInterval; //! Combines flags HInterval, VInterval
             static const int intervalTexte
                 = HIntervalTexte
                 | VIntervalTexte; //! Combines flags HIntervalTexte,
-                                   //! VIntervalTexte
+                                  //! VIntervalTexte
             static const int autoGrid
                 = AutoGridHeight | AutoGridWidth
                 | Raster; //! Combines flags AutoGridHeight,
@@ -225,7 +225,7 @@ namespace Framework
             static const int autoInterval
                 = AutoIntervalHeight
                 | AutoIntervalWidth; //! Combines flags AutoIntervalHeight,
-                                       //! AutoIntervalWidth
+                                     //! AutoIntervalWidth
         };
 
         //! Style of the diagram
@@ -275,13 +275,13 @@ namespace Framework
     protected:
         DiagramData* daten;
         bool changed;
-        Critical* lock;
+        ReadWriteLock* lock;
 
     public:
         //! Constructor
         //! \param lock A pointer to the Critical used to make the diagram class
         //! that inherits from this class thread-safe
-        DLLEXPORT BaseDiagram(Critical* lock);
+        DLLEXPORT BaseDiagram(ReadWriteLock* lock);
         //! Destructor
         DLLEXPORT virtual ~BaseDiagram();
         //! Sets a pointer to the diagram data
@@ -303,10 +303,12 @@ namespace Framework
         //! \param f The color in A8R8G8B8 format
         DLLEXPORT void setGridColor(int f);
         //! Sets the interval width
-        //! \param br The distance between values 0 and 1 on the X axis in pixels
+        //! \param br The distance between values 0 and 1 on the X axis in
+        //! pixels
         DLLEXPORT void setHIntervalWidth(double br);
         //! Sets the interval height
-        //! \param hi The distance between values 0 and 1 on the Y axis in pixels
+        //! \param hi The distance between values 0 and 1 on the Y axis in
+        //! pixels
         DLLEXPORT void setVIntervalHeight(double hi);
         //! Sets the color of the X axis
         //! \param f The color in A8R8G8B8 format
@@ -529,7 +531,7 @@ namespace Framework
     //! A 2D GUI Framework drawing that displays diagram data as
     //! line graphs
     class LineDiagram : public DrawableBackground,
-                  public BaseDiagram
+                        public BaseDiagram
     {
     public:
         class Style : public DrawableBackground::Style

+ 26 - 27
Drawing.cpp

@@ -105,14 +105,14 @@ void Drawable::setToolTipZ(ToolTip* tt)
     toolTipRequested = 0;
 }
 
-void Drawable::lockDrawable()
+Lock& Drawable::readLock()
 {
-    cs.lock();
+    return rwLock.getReadLock();
 }
 
-void Drawable::unlockDrawable()
+Lock& Drawable::writeLock()
 {
-    cs.unlock();
+    return rwLock.getWriteLock();
 }
 
 void Drawable::setMouseEventParameter(void* p) // sets the mouse event parameter
@@ -191,8 +191,7 @@ void Drawable::setPostKeyboardEvent(
 
 void Drawable::doPublicMouseEvent(MouseEvent& me) // calls Mak
 {
-    bool lock = hasStyle(Style::MELockDrawable);
-    if (lock) lockDrawable();
+    rwLock.lockRead();
     bool inside = isPointInside(me.mx, me.my);
     if (!me.insideParent || me.processed || !inside)
     {
@@ -215,7 +214,7 @@ void Drawable::doPublicMouseEvent(MouseEvent& me) // calls Mak
         || (!inside && hasStyleNot(Style::MEIgnoreInside))
         || (hasStyleNot(Style::Visible) && hasStyleNot(Style::MEIgnoreVisible)))
     {
-        if (lock) unlockDrawable();
+        rwLock.unlockRead();
         return;
     }
     if (inside && me.id == ME_PLeft) addStyle(Style::Focus);
@@ -260,7 +259,7 @@ void Drawable::doPublicMouseEvent(MouseEvent& me) // calls Mak
             me.processed = nMak(nmakParam, this, me);
     }
     me.mx = old.x, me.my = old.y;
-    if (lock) unlockDrawable();
+    rwLock.unlockRead();
 }
 
 void Drawable::doKeyboardEvent(KeyboardEvent& te) // calls Tak
@@ -272,40 +271,40 @@ void Drawable::doKeyboardEvent(KeyboardEvent& te) // calls Tak
 
 void Drawable::setPosition(const Point& pos) // sets the position
 {
-    lockDrawable();
+    rwLock.lockWrite();
     if (this->pos != pos) rend = 1;
     this->pos = pos;
-    unlockDrawable();
+    rwLock.unlockWrite();
 }
 
 void Drawable::setX(int xPos)
 {
-    lockDrawable();
+    rwLock.lockWrite();
     if (pos.x != xPos)
     {
         rend = 1;
         pos.x = xPos;
     }
-    unlockDrawable();
+    rwLock.unlockWrite();
 }
 
 void Drawable::setY(int yPos)
 {
-    lockDrawable();
+    rwLock.lockWrite();
     if (pos.y != yPos)
     {
         rend = 1;
         pos.y = yPos;
     }
-    unlockDrawable();
+    rwLock.unlockWrite();
 }
 
 void Drawable::setSize(const Point& gr) // sets the size
 {
-    lockDrawable();
+    rwLock.lockWrite();
     if (this->gr != gr) rend = 1;
     this->gr = gr;
-    unlockDrawable();
+    rwLock.unlockWrite();
 }
 
 void Drawable::setPosition(int x, int y) // sets the position
@@ -320,18 +319,18 @@ void Drawable::setSize(int x, int y) // sets the size
 
 void Drawable::setWidth(int width)
 {
-    lockDrawable();
+    rwLock.lockWrite();
     if (this->gr.x != width) rend = 1;
     gr.x = width;
-    unlockDrawable();
+    rwLock.unlockWrite();
 }
 
 void Drawable::setHeight(int height)
 {
-    lockDrawable();
+    rwLock.lockWrite();
     if (this->gr.y != height) rend = 1;
     gr.y = height;
-    unlockDrawable();
+    rwLock.unlockWrite();
 }
 
 bool Drawable::tick(double tickval)
@@ -774,10 +773,10 @@ void DrawableBackground::render(Image& rObj)
     innenSize.x = gr.x;
     innenSize.y = gr.y;
     if (hasStyleNot(Style::Visible)) return;
-    lockDrawable();
+    rwLock.lockRead();
     if (!rObj.setDrawOptions(pos.x, pos.y, gr.x, gr.y))
     {
-        unlockDrawable();
+        rwLock.unlockRead();
         return;
     }
     Drawable::render(rObj);
@@ -795,7 +794,7 @@ void DrawableBackground::render(Image& rObj)
     if (!rObj.setDrawOptions(rbr, rbr, gr.x - rbr * 2, gr.y - rbr * 2))
     {
         rObj.releaseDrawOptions();
-        unlockDrawable();
+        rwLock.unlockRead();
         return;
     }
     bool vs = vertikalScrollBar && hasStyle(Style::VScroll);
@@ -815,7 +814,7 @@ void DrawableBackground::render(Image& rObj)
             {
                 rObj.releaseDrawOptions();
                 rObj.releaseDrawOptions();
-                unlockDrawable();
+                rwLock.unlockRead();
                 return;
             }
             horizontalScrollBar->update(
@@ -827,7 +826,7 @@ void DrawableBackground::render(Image& rObj)
             {
                 rObj.releaseDrawOptions();
                 rObj.releaseDrawOptions();
-                unlockDrawable();
+                rwLock.unlockRead();
                 return;
             }
         }
@@ -843,7 +842,7 @@ void DrawableBackground::render(Image& rObj)
         {
             rObj.releaseDrawOptions();
             rObj.releaseDrawOptions();
-            unlockDrawable();
+            rwLock.unlockRead();
             return;
         }
     }
@@ -887,7 +886,7 @@ void DrawableBackground::render(Image& rObj)
     if (vs || hs) rObj.releaseDrawOptions();
     rObj.releaseDrawOptions();
     rObj.releaseDrawOptions();
-    unlockDrawable();
+    rwLock.unlockRead();
 }
 
 // Returns the width of the interior area of the drawing in pixels

+ 33 - 32
Drawing.h

@@ -4,23 +4,23 @@
 #include <functional>
 
 #include "Critical.h"
+#include "KeyboardEvent.h"
 #include "MouseEvent.h"
 #include "Point.h"
 #include "ReferenceCounter.h"
-#include "KeyboardEvent.h"
 
 namespace Framework
 {
-    struct MouseEvent;     //! MouseEvent.h
+    struct MouseEvent;    //! MouseEvent.h
     struct KeyboardEvent; //! KeyboardEvent.h
-    class Image;              //! Image.h
-    class Drawable;         //! From this file
-    class ToolTip;           //! ToolTip.h
-    class Screen;        //! Screen.h
-    class Border;            //! Border.h
-    class AlphaField;         //! AlphaField.h
-    class VScrollBar;        //! Scroll.h
-    class HScrollBar;        //! Scroll.h
+    class Image;          //! Image.h
+    class Drawable;       //! From this file
+    class ToolTip;        //! ToolTip.h
+    class Screen;         //! Screen.h
+    class Border;         //! Border.h
+    class AlphaField;     //! AlphaField.h
+    class VScrollBar;     //! Scroll.h
+    class HScrollBar;     //! Scroll.h
     class Font;
 
     //! A drawing element for the 2D GUI Framework
@@ -34,14 +34,12 @@ namespace Framework
             static const __int64 Visible = 0x00001;
             //! If this style is set, the user can interact with the drawing
             static const __int64 Allowed = 0x00002;
-            //! If this style is set, keyboard events are processed by the drawing
+            //! If this style is set, keyboard events are processed by the
+            //! drawing
             static const __int64 Focus = 0x00004;
             //! If this style is set, mouse events are processed even when
             //! the object is not visible
             static const __int64 MEIgnoreVisible = 0x0800000000000000;
-            //! If this style is set, the thread locks the object while
-            //! the mouse event is being processed
-            static const __int64 MELockDrawable = 0x1000000000000000;
             //! If this style is set, mouse events are processed even when
             //! they are outside the drawing
             static const __int64 MEIgnoreInside = 0x2000000000000000;
@@ -65,7 +63,7 @@ namespace Framework
         MouseAction nMak;
         KeyboardAction nTak;
         bool mouseIn;
-        Critical cs;
+        ReadWriteLock rwLock;
         ToolTip* toolTip;
         __int64 style;
         bool rend;
@@ -99,18 +97,15 @@ namespace Framework
         //! Sets the tooltip
         //! \param tt The tooltip
         DLLEXPORT void setToolTipZ(ToolTip* tt);
-        //! This is necessary if multiple threads use the drawing simultaneously.
-        //! If lockDrawable() is called by two threads, the last one waits
-        //! until the first has called unlockDrawable().
-        DLLEXPORT void lockDrawable();
-        //! This is necessary if multiple threads use the drawing simultaneously.
-        //! If lockDrawable() is called by two threads, the last one waits
-        //! until the first has called unlockDrawable().
-        DLLEXPORT void unlockDrawable();
+        //! returns a read lock for the drawing.
+        DLLEXPORT Lock& readLock();
+        //! returns a write lock for the drawing.
+        DLLEXPORT Lock& writeLock();
         //! Sets the parameter passed to the callback function on a mouse event
         //! \param p The parameter
         DLLEXPORT void setMouseEventParameter(void* p);
-        //! Sets the parameter passed to the callback function on a keyboard event
+        //! Sets the parameter passed to the callback function on a keyboard
+        //! event
         //! \param p The parameter
         DLLEXPORT void setKeyboardEventParameter(void* p);
         //! Sets the callback function to be called on a mouse event.
@@ -326,7 +321,8 @@ namespace Framework
         //! Style::Background) \param fc The background color in A8R8G8B8 format
         DLLEXPORT void setBackgroundColor(int fc);
         //! Sets a pointer to the AlphaField (requires drawing flag:
-        //! Style::Buffered) \param buff The AlphaField to draw over the background
+        //! Style::Buffered) \param buff The AlphaField to draw over the
+        //! background
         DLLEXPORT void setAlphaFieldZ(AlphaField* buff);
         //! Sets the strength of the AlphaField (requires drawing flag:
         //! Style::Buffered) \param st The strength of the AlphaField drawn
@@ -347,20 +343,24 @@ namespace Framework
         //! Style::Border) \param fc The color in A8R8G8B8 format
         DLLEXPORT void setBorderColor(int fc);
         //! Sets the scroll speed of the vertical scroll bar (requires drawing
-        //! flag: Style::VScroll) \param ks The scroll speed in pixels per mouse click
+        //! flag: Style::VScroll) \param ks The scroll speed in pixels per mouse
+        //! click
         DLLEXPORT void setVerticalClickScroll(int ks);
         //! Scrolls to a specific position on the vertical scroll bar
-        //! (requires drawing flag: Style::VScroll) \param pos The scroll offset in pixels
+        //! (requires drawing flag: Style::VScroll) \param pos The scroll offset
+        //! in pixels
         DLLEXPORT void setVerticalScrollPos(int pos);
         //! Sets the color of the vertical scroll bar (requires drawing flag:
         //! Style::VScroll) \param f The foreground color in A8R8G8B8 format
         //! \param bgF The background color in A8R8G8B8 format
         DLLEXPORT void setVerticalScrollColor(int f, int bgF);
         //! Sets the scroll speed of the horizontal scroll bar (requires drawing
-        //! flag: Style::HScroll) \param ks The scroll speed in pixels per mouse click
+        //! flag: Style::HScroll) \param ks The scroll speed in pixels per mouse
+        //! click
         DLLEXPORT void setHorizontalClickScroll(int ks);
         //! Scrolls to a specific position on the horizontal scroll bar
-        //! (requires drawing flag: Style::HScroll) \param pos The scroll offset in pixels
+        //! (requires drawing flag: Style::HScroll) \param pos The scroll offset
+        //! in pixels
         DLLEXPORT void setHorizontalScrollPos(int pos);
         //! Sets the color of the horizontal scroll bar (requires drawing flag:
         //! Style::HScroll) \param f The foreground color in A8R8G8B8 format
@@ -368,7 +368,8 @@ namespace Framework
         DLLEXPORT void setHorizontalScrollColor(int f, int bgF);
         //! Updates the drawing background
         //! \param tickVal The elapsed time in seconds since the last call
-        //! of this function \return 1 if the image needs to be redrawn. 0 otherwise
+        //! of this function \return 1 if the image needs to be redrawn. 0
+        //! otherwise
         DLLEXPORT bool tick(double tickVal) override;
         //! Renders the background of a drawing to rObj
         DLLEXPORT void render(Image& rObj) override;
@@ -420,8 +421,8 @@ namespace Framework
         DLLEXPORT int getHorizontalScrollPos() const;
         //! Returns the color of the horizontal scroll bar in A8R8G8B8 format
         DLLEXPORT int getHorizontalScrollColor() const;
-        //! Returns the background color of the horizontal scroll bar in A8R8G8B8
-        //! format
+        //! Returns the background color of the horizontal scroll bar in
+        //! A8R8G8B8 format
         DLLEXPORT int getHorizontalScrollBackground() const;
         //! Creates a copy of the drawing that can be modified without
         //! affecting the original

+ 0 - 2
Framework Linux.vcxproj

@@ -141,7 +141,6 @@
     <ClCompile Include="InitFile.cpp" />
     <ClCompile Include="InMemoryBuffer.cpp" />
     <ClCompile Include="JSON.cpp" />
-    <ClCompile Include="JsonEditor.cpp" />
     <ClCompile Include="Camera2D.cpp" />
     <ClCompile Include="Key.cpp" />
     <ClCompile Include="Button.cpp" />
@@ -166,7 +165,6 @@
     <ClInclude Include="Console.h" />
     <ClInclude Include="DataValidator.h" />
     <ClInclude Include="Iterator.h" />
-    <ClInclude Include="JsonEditor.h" />
     <ClInclude Include="Logging.h" />
     <ClInclude Include="RCPointer.h" />
     <ClCompile Include="Reader.cpp" />

+ 0 - 2
Framework.vcxproj

@@ -209,7 +209,6 @@ copy "x64\Release\Framework.dll" "..\..\Spiele Platform\SMP\Fertig\x64\framework
     <ClInclude Include="Console.h" />
     <ClInclude Include="DataValidator.h" />
     <ClInclude Include="Iterator.h" />
-    <ClInclude Include="JsonEditor.h" />
     <ClInclude Include="Logging.h" />
     <ClInclude Include="Regex.h" />
     <ClInclude Include="Base64.h" />
@@ -317,7 +316,6 @@ copy "x64\Release\Framework.dll" "..\..\Spiele Platform\SMP\Fertig\x64\framework
     <ClCompile Include="SelectionBox.cpp" />
     <ClCompile Include="Console.cpp" />
     <ClCompile Include="DataValidator.cpp" />
-    <ClCompile Include="JsonEditor.cpp" />
     <ClCompile Include="Logging.cpp" />
     <ClCompile Include="Regex.cpp" />
     <ClCompile Include="Base64.cpp" />

+ 0 - 6
Framework.vcxproj.filters

@@ -376,9 +376,6 @@
     <ClInclude Include="XML.h">
       <Filter>Framework\Data\XML</Filter>
     </ClInclude>
-    <ClInclude Include="JsonEditor.h">
-      <Filter>Framework\Data\JSON</Filter>
-    </ClInclude>
     <ClInclude Include="Stack.h">
       <Filter>Framework\Data</Filter>
     </ClInclude>
@@ -645,9 +642,6 @@
     <ClCompile Include="XML.cpp">
       <Filter>Framework\Data\XML</Filter>
     </ClCompile>
-    <ClCompile Include="JsonEditor.cpp">
-      <Filter>Framework\Data\JSON</Filter>
-    </ClCompile>
     <ClCompile Include="DataValidator.cpp">
       <Filter>Framework\Data\Abstract</Filter>
     </ClCompile>

+ 7 - 2
Global.cpp

@@ -19,11 +19,18 @@
 #    pragma comment(lib, "gdiplus.lib")
 #    include "Mouse.h"
 #    include "Window.h"
+#else
+#    include <unistd.h>
 #endif
 
 void Framework::initFramework(HINSTANCE__* hInst)
 {
     if (isInitialized) return;
+#ifdef WIN32
+    currentThreadId = GetCurrentThreadId();
+#else
+    currentThreadId = gettid();
+#endif
     loggingHandler = new Logging::LoggingHandler();
     thRegister = new ThreadRegister();
 #ifdef WIN32
@@ -35,7 +42,6 @@ void Framework::initFramework(HINSTANCE__* hInst)
 #endif
     for (int i = 0; i < 3; ++i)
         MouseState[i] = 0;
-    TextureList::init();
     dlls = new DLLRegister();
     _hinst = hInst;
     isInitialized = 1;
@@ -48,7 +54,6 @@ void Framework::releaseFramework()
     if (!isInitialized) return;
     thRegister->cleanUpClosedThreads();
     dlls->release();
-    TextureList::destroy();
     delete thRegister;
     loggingHandler->release();
     isInitialized = 0;

+ 1 - 1
Globals.h

@@ -38,12 +38,12 @@ namespace Framework
     Global bool MouseState[3];
     Global bool isInitialized;
     Global ThreadRegister* thRegister;
-    Global Critical logC;
     Global HINSTANCE__* _hinst;
     Global DLLRegister* dlls;
     Global bool debugDX;
     Global bool cursorVisible;
     Global Logging::LoggingHandler* loggingHandler;
+    Global thread_local int currentThreadId;
 
 #ifdef WIN32
     //! Returns the mouse coordinates on the screen

+ 12 - 10
GraphicsApi.cpp

@@ -1,9 +1,9 @@
 #include "GraphicsApi.h"
 
 #include "Image.h"
-#include "Window.h"
 #include "Model3D.h"
 #include "Model3DList.h"
+#include "Window.h"
 
 using namespace Framework;
 
@@ -81,42 +81,44 @@ bool GraphicsApi::isFullScreen() const
 // returns the specified model without increased reference counter
 Model3DData* GraphicsApi::zModel(const char* name)
 {
-    cs.lock();
+    rwLock.lockRead();
     Model3DData* data = modelList->zModel(name);
-    cs.unlock();
+    rwLock.unlockRead();
     return data;
 }
 
 // returns the specified model with increased reference counter
 Model3DData* GraphicsApi::getModel(const char* name)
 {
-    cs.lock();
+    rwLock.lockRead();
     Model3DData* data = modelList->getModel(name);
-    cs.unlock();
+    rwLock.unlockRead();
     return data;
 }
 
 // creates a new empty Model3DData object if the model does not exist yet
 Model3DData* GraphicsApi::createModel(const char* name)
 {
-    cs.lock();
+    rwLock.lockRead();
     if (modelList->hasModel(name))
     {
-        cs.unlock();
+        rwLock.unlockRead();
         return 0;
     }
     Model3DData* model = new Model3DData(
         createVertexBuffer(), createIndexBuffer(), nextModelId++);
+    rwLock.lockWrite();
     modelList->addModel(model, name);
-    cs.unlock();
+    rwLock.unlockWrite();
+    rwLock.unlockRead();
     return dynamic_cast<Model3DData*>(model->getThis());
 }
 
 // check if a model exists
 bool GraphicsApi::hasModel(const char* name)
 {
-    cs.lock();
+    rwLock.lockRead();
     bool res = modelList->hasModel(name);
-    cs.unlock();
+    rwLock.unlockRead();
     return res;
 }

+ 12 - 8
GraphicsApi.h

@@ -1,8 +1,8 @@
 #pragma once
 
-#include "Screen.h"
-#include "Plane3D.h"
 #include "Mat4.h"
+#include "Plane3D.h"
+#include "Screen.h"
 #include "Vec2.h"
 
 //! DirectX 12 Types
@@ -95,7 +95,7 @@ namespace Framework
         Vec2<int> backBufferSize;
         Model3DList* modelList;
         int nextModelId;
-        Critical cs;
+        ReadWriteLock rwLock;
 
         bool fullScreen;
 
@@ -159,7 +159,8 @@ namespace Framework
             bool fill2D, bool fill3D, int fillColor) override;
         DLLEXPORT void renderKamera(Cam3D* zKamera) override;
         DLLEXPORT void presentFrame() override;
-        DLLEXPORT Texture* createOrGetTexture(const char* name, Image* b) override;
+        DLLEXPORT Texture* createOrGetTexture(
+            const char* name, Image* b) override;
         DLLEXPORT Image* zUIRenderImage() const override;
 
         DLLEXPORT virtual DXBuffer* createStructuredBuffer(int eSize) override;
@@ -169,6 +170,7 @@ namespace Framework
     {
     private:
         ID3D11Device* d3d11Device;
+        Critical deviceLock;
         ID3D11DeviceContext* d3d11Context;
         IDXGISwapChain* d3d11SpawChain;
         Texture* uiTexture;
@@ -218,7 +220,8 @@ namespace Framework
         DLLEXPORT void renderKamera(Cam3D* zKamera) override;
         DLLEXPORT void renderKamera(Cam3D* zKamera, Texture* zTarget) override;
         DLLEXPORT void presentFrame() override;
-        DLLEXPORT Texture* createOrGetTexture(const char* name, Image* b) override;
+        DLLEXPORT Texture* createOrGetTexture(
+            const char* name, Image* b) override;
         DLLEXPORT Image* zUIRenderImage() const override;
         DLLEXPORT virtual DXBuffer* createStructuredBuffer(int eSize) override;
         //! Checks whether a sphere is in the visible space of the world and
@@ -281,10 +284,11 @@ namespace Framework
         DLLEXPORT void beginFrame(
             bool fill2D, bool fill3D, int fillColor) override;
         DLLEXPORT void renderKamera(Cam3D* zKamera) override;
-        //! TODO: DLLEXPORT void renderKamera( Cam3D* zKamera, Texture* zTarget )
-        //! override;
+        //! TODO: DLLEXPORT void renderKamera( Cam3D* zKamera, Texture* zTarget
+        //! ) override;
         DLLEXPORT void presentFrame() override;
-        DLLEXPORT Texture* createOrGetTexture(const char* name, Image* b) override;
+        DLLEXPORT Texture* createOrGetTexture(
+            const char* name, Image* b) override;
         DLLEXPORT Image* zUIRenderImage() const override;
         DLLEXPORT virtual DXBuffer* createStructuredBuffer(int eSize) override;
         //! Checks whether a sphere is in the visible space of the world and

+ 12 - 14
Image.cpp

@@ -6,10 +6,10 @@
 #endif
 
 #include "AlphaField.h"
+#include "Border.h"
 #include "FileSystem.h"
 #include "Globals.h"
 #include "MouseEvent.h"
-#include "Border.h"
 #include "Scroll.h"
 #include "Text.h"
 #include "ToolTip.h"
@@ -396,8 +396,8 @@ bool Image::isAreaDrawable(int x, int y, int b, int h)
 
 // When this flag is set, during alpha blending if the previous
 // color is 0, only the new one is copied with its alpha value. This is useful
-// for use in the 3D screen, where the drawn image is later displayed using alpha
-// blending
+// for use in the 3D screen, where the drawn image is later displayed using
+// alpha blending
 void Image::setAlpha3D(bool erlaubt)
 {
     alpha3D = erlaubt;
@@ -700,8 +700,7 @@ void Image::setPixelDP(int i, int f)
     rend = 1;
 }
 
-void Image::drawLineH(
-    int x, int y, int len, int f) // draws a horizontal line
+void Image::drawLineH(int x, int y, int len, int f) // draws a horizontal line
 {
     if (alpha[alphaCount] == 0xFF) return;
     if (alpha[alphaCount])
@@ -736,8 +735,7 @@ void Image::drawLineH(
     rend = 1;
 }
 
-void Image::drawLineV(
-    int x, int y, int len, int f) // draws a vertical line
+void Image::drawLineV(int x, int y, int len, int f) // draws a vertical line
 {
     if (alpha[alphaCount] == 0xFF) return;
     if (alpha[alphaCount])
@@ -2926,7 +2924,7 @@ ImageView::ImageView()
     : DrawableBackground(),
       bild(0)
 {
-    style = Style::MELockDrawable;
+    style = 0;
     mak = _ret1ME;
 }
 
@@ -2997,10 +2995,10 @@ void ImageView::render(Image& zRObj) // draws to zRObj
     if (hasStyle(Style::Visible))
     {
         DrawableBackground::render(zRObj);
-        lockDrawable();
+        rwLock.lockRead();
         if (!zRObj.setDrawOptions(innenPosition, innenSize))
         {
-            unlockDrawable();
+            rwLock.unlockRead();
             return;
         }
         if (bild)
@@ -3032,7 +3030,7 @@ void ImageView::render(Image& zRObj) // draws to zRObj
                 if (!zRObj.setDrawOptions(x, y, br, hi))
                 {
                     zRObj.releaseDrawOptions();
-                    unlockDrawable();
+                    rwLock.unlockRead();
                     return;
                 }
                 if (hasStyle(Style::Alpha))
@@ -3051,7 +3049,7 @@ void ImageView::render(Image& zRObj) // draws to zRObj
             }
         }
         zRObj.releaseDrawOptions();
-        unlockDrawable();
+        rwLock.unlockRead();
     }
 }
 
@@ -3095,8 +3093,8 @@ Image* Framework::loadImage(const char* pfad, Text* zError)
 {
     Text p = pfad;
     Text* txt = p.getTeilText(p.positionOf('.', p.countOf('.') - 1));
-    if (!(txt->isEqual(".bmp") || txt->isEqual(".jpg")
-            || txt->isEqual(".gif") || txt->isEqual(".png")))
+    if (!(txt->isEqual(".bmp") || txt->isEqual(".jpg") || txt->isEqual(".gif")
+            || txt->isEqual(".png")))
     {
         zError->setText("Die Angegebene File ist keine gueltige ImageFile!");
         txt->release();

+ 3 - 3
List.cpp

@@ -606,10 +606,10 @@ void SelectionList::render(Image& zRObj) // draws to zRObj
     if (!DrawableBackground::hasStyle(Style::Visible)) return;
     removeStyle(Style::HScroll);
     DrawableBackground::render(zRObj);
-    lockDrawable();
+    rwLock.lockRead();
     if (!zRObj.setDrawOptions(innenPosition, innenSize))
     {
-        unlockDrawable();
+        rwLock.unlockRead();
         return;
     }
     int rbr = 0;
@@ -812,7 +812,7 @@ void SelectionList::render(Image& zRObj) // draws to zRObj
             vertikalScrollBar->getScrollData()->max = maxHeight;
     }
     zRObj.releaseDrawOptions();
-    unlockDrawable();
+    rwLock.unlockRead();
 }
 
 int SelectionList::getClickEntry(int my)

+ 11 - 8
Progress.cpp

@@ -1,9 +1,9 @@
 #include "Progress.h"
 
 #include "AlphaField.h"
-#include "Image.h"
 #include "Border.h"
 #include "Font.h"
+#include "Image.h"
 #include "Scroll.h"
 #include "Text.h"
 
@@ -113,7 +113,8 @@ void ProgressBar::setFBgImageZ(Image* b) // sets the completion background image
     rend = 1;
 }
 
-void ProgressBar::setFBgImage(Image* b) // copies into the completion background image
+void ProgressBar::setFBgImage(
+    Image* b) // copies into the completion background image
 {
     if (!fBgImage) fBgImage = new Image();
     fBgImage->newImage(b->getWidth(), b->getHeight(), 0);
@@ -152,12 +153,12 @@ void ProgressBar::setSSize(unsigned char gr) // sets the font size
 void ProgressBar::render(Image& zRObj) // renders into zRObj
 {
     if (!hasStyle(Style::Visible)) return;
-    lockDrawable();
+    rwLock.lockRead();
     removeStyle(Style::VScroll | Style::HScroll);
     DrawableBackground::render(zRObj);
     if (!zRObj.setDrawOptions(pos, gr))
     {
-        unlockDrawable();
+        rwLock.unlockRead();
         return;
     }
     int xx = 0;
@@ -182,7 +183,7 @@ void ProgressBar::render(Image& zRObj) // renders into zRObj
     if (!zRObj.setDrawOptions(xx, yy, b, h))
     {
         zRObj.releaseDrawOptions();
-        unlockDrawable();
+        rwLock.unlockRead();
         return;
     }
     int rbr = 0;
@@ -253,7 +254,7 @@ void ProgressBar::render(Image& zRObj) // renders into zRObj
             fontColor);
     }
     zRObj.releaseDrawOptions();
-    unlockDrawable();
+    rwLock.unlockRead();
 }
 
 // constant
@@ -284,7 +285,8 @@ Border* ProgressBar::zFBorder() const
     return fBorder;
 }
 
-AlphaField* ProgressBar::getFAlphaField() const // returns the completion AlphaField
+AlphaField*
+ProgressBar::getFAlphaField() const // returns the completion AlphaField
 {
     if (fBuffer) return dynamic_cast<AlphaField*>(fBuffer->getThis());
     return 0;
@@ -300,7 +302,8 @@ int ProgressBar::getFBgColor() const // returns the completion background color
     return fBgF;
 }
 
-Image* ProgressBar::getFBgImage() const // returns the completion background image
+Image*
+ProgressBar::getFBgImage() const // returns the completion background image
 {
     if (fBgImage) return dynamic_cast<Image*>(fBgImage->getThis());
     return 0;

+ 9 - 9
RenderThread.cpp

@@ -34,22 +34,22 @@ RenderTh::~RenderTh()
 }
 
 // non-constant
-void RenderTh::lock()
+Lock& RenderTh::readLock()
 {
-    cs.lock();
+    return rwLock.getReadLock();
 }
 
-void RenderTh::unlock()
+Lock& RenderTh::writeLock()
 {
-    cs.unlock();
+    return rwLock.getWriteLock();
 }
 
 void RenderTh::setScreen(Screen* bildschirm) // sets the screen
 {
-    lock();
+    rwLock.lockWrite();
     if (this->screen) this->screen->release();
     this->screen = bildschirm;
-    unlock();
+    rwLock.unlockWrite();
 }
 
 void RenderTh::thread() // Render loop
@@ -60,7 +60,7 @@ void RenderTh::thread() // Render loop
     double ausgleich = 0;
     while (!stop)
     {
-        lock();
+        rwLock.lockRead();
         if (screen && !pause)
         {
             if (renderFunktion)
@@ -70,7 +70,7 @@ void RenderTh::thread() // Render loop
             if (tickFunktion) tickFunktion(tickParameter, this, renderTickTime);
             screen->tick(renderTickTime);
             time += renderTickTime;
-            unlock();
+            rwLock.unlockRead();
             if (time > 1)
             {
                 time -= 1;
@@ -83,7 +83,7 @@ void RenderTh::thread() // Render loop
         }
         else
         {
-            unlock();
+            rwLock.unlockRead();
             Sleep(100);
         }
         ausgleich += 1.0 / maxFps - renderTickTime;

+ 5 - 9
RenderThread.h

@@ -26,7 +26,7 @@ namespace Framework
         std::function<void(void*, void*, Image*)> renderFunktion;
         std::function<void(void*, void*, double)> tickFunktion;
         bool pause;
-        Critical cs;
+        ReadWriteLock rwLock;
         int maxFps;
         bool quiet;
 
@@ -35,14 +35,10 @@ namespace Framework
         DLLEXPORT RenderTh();
         //! Destructor
         DLLEXPORT ~RenderTh();
-        //! This is necessary if multiple threads use the object simultaneously.
-        //! If lock() is called by two threads, the latter waits until the
-        //! first has called unlock().
-        DLLEXPORT void lock();
-        //! This is necessary if multiple threads use the object simultaneously.
-        //! If lock() is called by two threads, the latter waits until the
-        //! first has called unlock().
-        DLLEXPORT void unlock();
+        //! returns a lock for reading the object.
+        DLLEXPORT Lock& readLock();
+        //! returns a lock for writing the object.
+        DLLEXPORT Lock& writeLock();
         //! Sets the screen object to be managed
         //! \param screen The screen
         DLLEXPORT void setScreen(Screen* screen);

+ 60 - 61
Screen.cpp

@@ -51,7 +51,7 @@ Screen::Screen(NativeWindow* f)
 // Destructor
 Screen::~Screen()
 {
-    lock();
+    rwLock.lockWrite();
 #ifdef WIN32
     if (fenster) fenster->release();
 #endif
@@ -60,14 +60,14 @@ Screen::~Screen()
     renderTime->release();
     if (onTop) onTop->release();
     if (api) api->release();
-    unlock();
+    rwLock.unlockWrite();
 }
 
 void Screen::postAction(std::function<void()> action)
 {
-    cs.lock();
+    rwLock.lockWrite();
     actions.push(action);
-    cs.unlock();
+    rwLock.unlockWrite();
 }
 
 void Screen::setHandleUserInputsOnTick(bool handleOnTick)
@@ -76,14 +76,14 @@ void Screen::setHandleUserInputsOnTick(bool handleOnTick)
 }
 
 // non-constant
-void Screen::lock()
+Lock& Screen::readLock()
 {
-    cs.lock();
+    return rwLock.getReadLock();
 }
 
-void Screen::unlock()
+Lock& Screen::writeLock()
 {
-    cs.unlock();
+    return rwLock.getWriteLock();
 }
 
 void Screen::setFill(bool f)
@@ -94,9 +94,9 @@ void Screen::setFill(bool f)
 // Updates the objects that manage the graphics card
 void Screen::update()
 {
-    lock();
+    rwLock.lockRead();
     api->update();
-    unlock();
+    rwLock.unlockRead();
 }
 
 void Screen::setTestRend(
@@ -108,10 +108,10 @@ void Screen::setTestRend(
 void Screen::setRenderDrawables(
     bool rO) // specifies whether drawings are rendered
 {
-    lock();
+    rwLock.lockWrite();
     renderDrawables = rO;
     rend = 1;
-    unlock();
+    rwLock.unlockWrite();
 }
 
 void Screen::setOnTop(
@@ -123,11 +123,11 @@ void Screen::setOnTop(
 
 void Screen::setOnTopDrawable(Drawable* obj) // sets the onTop drawing
 {
-    lock();
+    rwLock.lockWrite();
     if (onTop) onTop->release();
     onTop = obj;
     rend = 1;
-    unlock();
+    rwLock.unlockWrite();
 }
 
 void Screen::setdeckColor(int f) // sets the overlay color
@@ -138,30 +138,21 @@ void Screen::setdeckColor(int f) // sets the overlay color
 
 void Screen::addMember(Drawable* obj) // Adds a drawing
 {
-    lock();
+    rwLock.lockWrite();
     members->add(obj);
     rend = 1;
-    unlock();
+    rwLock.unlockWrite();
 }
 
 void Screen::removeMember(Drawable* zObj) // Removes a drawing
 {
-    lock();
+    rwLock.lockWrite();
     for (int i = 0; i < members->getEntryCount(); i++)
     {
         if (members->z(i) == zObj) members->remove(i);
     }
     rend = 1;
-    unlock();
-}
-
-// Draws an image and presents it on the screen
-void Screen::render()
-{
-    lock();
-    api->update();
-    rend = 1;
-    unlock();
+    rwLock.unlockWrite();
 }
 
 void Screen::setFillColor(int f) // sets the fill color
@@ -172,25 +163,32 @@ void Screen::setFillColor(int f) // sets the fill color
 
 void Screen::setFullscreen(bool vollbild) // sets fullscreen
 {
-    lock();
+    rwLock.lockRead();
     api->setFullScreen(vollbild);
-    unlock();
+    rwLock.unlockRead();
 }
 
 void Screen::tick(double tickval)
 {
-    lock();
+    rwLock.lockRead();
     while (!actions.empty())
     {
         actions.front()();
+        rwLock.lockWrite();
         actions.pop();
+        rwLock.unlockWrite();
     }
     if (!renderOnTop)
     {
         for (ArrayIterator<ToolTip*> i = tips->begin(); i; i++)
         {
             i->tick(tickval);
-            if (i->getReferenceCount() == 1) i.remove();
+            if (i->getReferenceCount() == 1)
+            {
+                rwLock.lockWrite();
+                i.remove();
+                rwLock.unlockWrite();
+            }
         }
         for (Drawable* i : *members)
             rend |= i->tick(tickval);
@@ -201,25 +199,30 @@ void Screen::tick(double tickval)
         for (ArrayIterator<ToolTip*> i = tips->begin(); i; i++)
         {
             i->tick(tickval);
-            if (i->getReferenceCount() == 1) i.remove();
+            if (i->getReferenceCount() == 1)
+            {
+                rwLock.lockWrite();
+                i.remove();
+                rwLock.unlockWrite();
+            }
         }
     }
-    unlock();
+    rwLock.unlockRead();
 }
 
 void Screen::setBackBufferSize(
     int Width, int height) // sets the size of the back buffer
 {
-    lock();
+    rwLock.lockRead();
     api->setBackBufferSize(Vec2<int>(Width, height));
-    unlock();
+    rwLock.unlockRead();
 }
 
 void Screen::setBackBufferSize(Point& size)
 {
-    lock();
+    rwLock.lockRead();
     api->setBackBufferSize(size);
-    unlock();
+    rwLock.unlockRead();
 }
 
 void Screen::doMouseEvent(MouseEvent& me) // sends mouse event
@@ -235,13 +238,12 @@ void Screen::doMouseEvent(MouseEvent& me) // sends mouse event
 #endif
     me.mx = (int)(me.mx * api->getBackBufferSize().x / (double)fBr + 0.5);
     me.my = (int)(me.my * api->getBackBufferSize().y / (double)fHi + 0.5);
-    lock();
+    rwLock.lockRead();
     if (!renderOnTop)
     {
         for (ArrayIterator<ToolTip*> i = tips->begin(); i; i++)
         {
             i->doPublicMouseEvent(me);
-            if (i->getReferenceCount() == 1) i.remove();
         }
         for (int i = members->getEntryCount() - 1; i >= 0; i--)
             members->z(i)->doPublicMouseEvent(me);
@@ -252,15 +254,14 @@ void Screen::doMouseEvent(MouseEvent& me) // sends mouse event
         for (ArrayIterator<ToolTip*> i = tips->begin(); i; i++)
         {
             i->doPublicMouseEvent(me);
-            if (i->getReferenceCount() == 1) i.remove();
         }
     }
-    unlock();
+    rwLock.unlockRead();
 }
 
 void Screen::doKeyboardEvent(KeyboardEvent& te) // sends keyboard event
 {
-    lock();
+    rwLock.lockRead();
     if (!renderOnTop)
     {
         for (int i = members->getEntryCount() - 1; i >= 0; i--)
@@ -269,17 +270,16 @@ void Screen::doKeyboardEvent(KeyboardEvent& te) // sends keyboard event
     for (ArrayIterator<ToolTip*> i = tips->begin(); i; i++)
     {
         i->doKeyboardEvent(te);
-        if (i->getReferenceCount() == 1) i.remove();
     }
-    unlock();
+    rwLock.unlockRead();
 }
 
 void Screen::addToolTip(ToolTip* tip) // adds a ToolTip
 {
-    lock();
+    rwLock.lockWrite();
     tips->add(tip);
     rend = 1;
-    unlock();
+    rwLock.unlockWrite();
 }
 
 // constant
@@ -411,7 +411,7 @@ void Screen2D::render() // Draws the image
     Image* ui = api->zUIRenderImage();
     if (ui)
     {
-        lock();
+        rwLock.lockRead();
         renderTime->measureStart();
         api->beginFrame(fill && (rend || !testRend), 0, fillColor);
         if (renderDrawables)
@@ -441,7 +441,7 @@ void Screen2D::render() // Draws the image
         if (renderOnTop && onTop) onTop->render(*ui);
         api->presentFrame();
         renderTime->measureEnd();
-        unlock();
+        rwLock.unlockRead();
     }
     rendering = 0;
     rend = 0;
@@ -498,15 +498,15 @@ Screen3D::~Screen3D()
 // non-constant
 void Screen3D::addKamera(Cam3D* obj) // Adds a camera
 {
-    lock();
+    rwLock.lockWrite();
     kameras->add(obj);
     rend3D = 1;
-    unlock();
+    rwLock.unlockWrite();
 }
 
 void Screen3D::removeKamera(Cam3D* zObj) // Removes a camera
 {
-    lock();
+    rwLock.lockWrite();
     for (int i = 0; kameras->z(i); i++)
     {
         if (kameras->z(i) == zObj)
@@ -516,16 +516,16 @@ void Screen3D::removeKamera(Cam3D* zObj) // Removes a camera
         }
     }
     rend3D = 1;
-    unlock();
+    rwLock.unlockWrite();
 }
 
 void Screen3D::tick(double tickval)
 {
-    lock();
+    rwLock.lockRead();
     __super::tick(tickval);
     for (Cam3D* k : *kameras)
         rend3D |= k->tick(tickval);
-    unlock();
+    rwLock.unlockRead();
     if (handleUserInputsOnTick)
     {
         queueCs.lock();
@@ -559,11 +559,11 @@ void Screen3D::doMouseEvent(MouseEvent& me) // sends mouse event
     }
     else
     {
-        lock();
+        rwLock.lockRead();
         __super::doMouseEvent(me);
         for (int i = kameras->getEntryCount() - 1; i >= 0; i--)
             kameras->z(i)->doMouseEvent(me);
-        unlock();
+        rwLock.unlockRead();
     }
 }
 
@@ -577,18 +577,18 @@ void Screen3D::doKeyboardEvent(KeyboardEvent& te) // sends keyboard event
     }
     else
     {
-        lock();
+        rwLock.lockRead();
         __super::doKeyboardEvent(te);
         for (int i = kameras->getEntryCount() - 1; i >= 0; i--)
             kameras->z(i)->doKeyboardEvent(te);
-        unlock();
+        rwLock.unlockRead();
     }
 }
 
 void Screen3D::render() // Draws the image
 {
     rendering = 1;
-    lock();
+    rwLock.lockRead();
     renderTime->measureStart();
     // Clear the back buffer.
     api->beginFrame(fill && (rend || !testRend),
@@ -626,13 +626,12 @@ void Screen3D::render() // Draws the image
             for (ArrayIterator<ToolTip*> i = tips->begin(); i; i++)
             {
                 i->render(*ui);
-                if (i->getReferenceCount() == 1) i.remove();
             }
         }
         if (renderOnTop && onTop) onTop->render(*ui);
     }
     api->presentFrame();
-    unlock();
+    rwLock.unlockRead();
     renderTime->measureEnd();
 #    ifdef _DEBUG
     // Logging::trace() << renderTime->getSekunden() << "\n";

+ 26 - 30
Screen.h

@@ -5,9 +5,9 @@
 
 #include "Array.h"
 #include "Critical.h"
+#include "KeyboardEvent.h"
 #include "MouseEvent.h"
 #include "Point.h"
-#include "KeyboardEvent.h"
 
 //! DirectX 11 Types
 
@@ -33,25 +33,25 @@ struct _D3DLOCKED_RECT;
 
 namespace Framework
 {
-    class Image;              //! Image.h
-    class NativeWindow;          //! Window.h
-    class Screen;        //! from this file
-    class Drawable;         //! Drawing.h
-    class Drawable3D;       //! Drawing3D.h
-    class Timer;        //! Time.h
-    struct MouseEvent;     //! MouseEvent.h
+    class Image;          //! Image.h
+    class NativeWindow;   //! Window.h
+    class Screen;         //! from this file
+    class Drawable;       //! Drawing.h
+    class Drawable3D;     //! Drawing3D.h
+    class Timer;          //! Time.h
+    struct MouseEvent;    //! MouseEvent.h
     struct KeyboardEvent; //! KeyboardEvent.h
-    class ToolTip;           //! Tooltip.h
-    class PixelShader;       //! Shader.h
-    class VertexShader;      //! Shader.h
-    class Cam3D;             //! Camera3D.h
-    class Render3D;          //! Render3D.h
-    class DXVertexBuffer;    //! DXBuffer.h
-    class DXIndexBuffer;     //! DXBuffer.h
-    class Texture;            //! Texture.h
-    class TextureModel;       //! TextureModel.h
-    class GraphicsApi;       //! GraphicsApi.h
-    class DirectX9;          //! GraphicsApi.h
+    class ToolTip;        //! Tooltip.h
+    class PixelShader;    //! Shader.h
+    class VertexShader;   //! Shader.h
+    class Cam3D;          //! Camera3D.h
+    class Render3D;       //! Render3D.h
+    class DXVertexBuffer; //! DXBuffer.h
+    class DXIndexBuffer;  //! DXBuffer.h
+    class Texture;        //! Texture.h
+    class TextureModel;   //! TextureModel.h
+    class GraphicsApi;    //! GraphicsApi.h
+    class DirectX9;       //! GraphicsApi.h
 
     enum GraphicApiType
     {
@@ -65,7 +65,7 @@ namespace Framework
     struct Monitor
     {
         int x, y, width,
-            height;     //! Coordinates of the monitor and its resolution
+            height;  //! Coordinates of the monitor and its resolution
         bool exists; //! Stores whether the monitor really exists
         Text name;
     };
@@ -84,7 +84,7 @@ namespace Framework
         bool renderDrawables;
         bool rendering;
         Timer* renderTime;
-        Critical cs;
+        ReadWriteLock rwLock;
         RCArray<ToolTip>* tips;
         bool testRend;
         bool fill;
@@ -110,14 +110,10 @@ namespace Framework
         //! rendering and ticks. This can lead to longer waiting times since the
         //! lock can not allways be aquired betwean two frames
         DLLEXPORT void setHandleUserInputsOnTick(bool handleOnTick);
-        //! This is necessary if multiple threads use the screen simultaneously.
-        //! If lock() is called by two threads, the last one waits until the
-        //! first has called unlock().
-        DLLEXPORT virtual void lock();
-        //! This is necessary if multiple threads use the screen simultaneously.
-        //! If lock() is called by two threads, the last one waits until the
-        //! first has called unlock().
-        DLLEXPORT virtual void unlock();
+        //! returns a lock for reading.
+        DLLEXPORT virtual Lock& readLock();
+        //! returns a lock for writing.
+        DLLEXPORT virtual Lock& writeLock();
         //! Specifies whether the screen is refilled with a color after each
         //! frame (set by default) \param f 1 if the image should be reset
         //! before drawing
@@ -153,7 +149,7 @@ namespace Framework
         //! counter)
         DLLEXPORT virtual void removeMember(Drawable* zObj);
         //! Draws an image and presents it on the screen
-        DLLEXPORT virtual void render();
+        DLLEXPORT virtual void render() = 0;
         //! Sets the color used to fill the image before drawing, if
         //! setFill(1) was set \param f The color in A8R8G8B8 format
         DLLEXPORT virtual void setFillColor(int f);

+ 37 - 26
SelectionBox.cpp

@@ -1,13 +1,13 @@
 #include "SelectionBox.h"
 
 #include "AlphaField.h"
-#include "Image.h"
-#include "Button.h"
-#include "MouseEvent.h"
 #include "Border.h"
+#include "Button.h"
 #include "Font.h"
-#include "Scroll.h"
+#include "Image.h"
 #include "KeyboardEvent.h"
+#include "MouseEvent.h"
+#include "Scroll.h"
 #include "Text.h"
 #include "TextField.h"
 #include "ToolTip.h"
@@ -200,7 +200,8 @@ void SelectionBox::setEventParam(void* p) // set event parameter
 }
 
 void SelectionBox::setEventAktion(
-    std::function<void(void*, SelectionBox*, int, int)> event) // set event action
+    std::function<void(void*, SelectionBox*, int, int)>
+        event) // set event action
 {
     this->eAk = event;
 }
@@ -325,8 +326,7 @@ void SelectionBox::setEntryBorderColor(int i, int f) // set entry border color
     rend = 1;
 }
 
-void SelectionBox::setEntryBorderWidth(
-    int i, int rbr) // set entry border width
+void SelectionBox::setEntryBorderWidth(int i, int rbr) // set entry border width
 {
     if (members->z(i)) members->z(i)->setBorderWidth(rbr);
     rend = 1;
@@ -431,7 +431,8 @@ void SelectionBox::setSelAlphaFieldZ(AlphaField* af) // set selection AlphaField
     rend = 1;
 }
 
-void SelectionBox::setSelAlphaFieldColor(int afF) // set selection AlphaField color
+void SelectionBox::setSelAlphaFieldColor(
+    int afF) // set selection AlphaField color
 {
     if (!selAf) selAf = new AlphaField();
     selAf->setColor(afF);
@@ -610,7 +611,8 @@ void SelectionBox::setMouseAlphaFieldZ(AlphaField* af) // set mouse AlphaField
     rend = 1;
 }
 
-void SelectionBox::setMouseAlphaFieldColor(int afF) // set mouse AlphaField color
+void SelectionBox::setMouseAlphaFieldColor(
+    int afF) // set mouse AlphaField color
 {
     if (!mouseAf) mouseAf = new AlphaField();
     mouseAf->setColor(afF);
@@ -923,14 +925,14 @@ void SelectionBox::render(Image& zRObj) // renders into zRObj
 {
     if (hasStyle(Style::Visible))
     {
-        lockDrawable();
+        rwLock.lockRead();
         int br = gr.x;
         int hi = gr.y + ausklappHeight;
         if ((ausklappHeight
                 && !zRObj.setDrawOptionsErzwingen(pos.x, pos.y, br, hi))
             || (!ausklappHeight && !zRObj.setDrawOptions(pos.x, pos.y, br, hi)))
         {
-            unlockDrawable();
+            rwLock.unlockRead();
             return;
         }
         int rbr = 0;
@@ -947,7 +949,7 @@ void SelectionBox::render(Image& zRObj) // renders into zRObj
                 && !zRObj.setDrawOptions(rbr, rbr, br - rbr * 2, hi - rbr * 2)))
         {
             zRObj.releaseDrawOptions();
-            unlockDrawable();
+            rwLock.unlockRead();
             return;
         }
         if (hasStyle(Style::Background))
@@ -1023,8 +1025,8 @@ void SelectionBox::render(Image& zRObj) // renders into zRObj
                             tf->setBackgroundImageZ(
                                 dynamic_cast<Image*>(selBgB->getThis()));
                             tmpHB = tf->hasStyle(TextField::Style::BImage);
-                            tf->setStyle(
-                                TextField::Style::BImage, hasStyle(Style::BImage));
+                            tf->setStyle(TextField::Style::BImage,
+                                hasStyle(Style::BImage));
                         }
                         if (hasStyle(Style::SelectionHAlpha))
                         {
@@ -1045,7 +1047,8 @@ void SelectionBox::render(Image& zRObj) // renders into zRObj
                 }
                 else
                 {
-                    if (hasMsStyle(selection, Style::SelectionBuffer) && msSelAf)
+                    if (hasMsStyle(selection, Style::SelectionBuffer)
+                        && msSelAf)
                     {
                         tmpBuffer = tf->getAlphaField();
                         tf->setAlphaFieldZ(msSelAf->get(selection));
@@ -1123,7 +1126,8 @@ void SelectionBox::render(Image& zRObj) // renders into zRObj
                 }
                 else
                 {
-                    if (hasMsStyle(selection, Style::SelectionBuffer) && msSelAf)
+                    if (hasMsStyle(selection, Style::SelectionBuffer)
+                        && msSelAf)
                     {
                         tf->setAlphaFieldZ(tmpBuffer);
                         tf->setStyle(TextField::Style::Buffered, tmpB);
@@ -1177,7 +1181,7 @@ void SelectionBox::render(Image& zRObj) // renders into zRObj
             {
                 zRObj.releaseDrawOptions();
                 zRObj.releaseDrawOptions();
-                unlockDrawable();
+                rwLock.unlockRead();
                 return;
             }
             int maxHeight = 0;
@@ -1269,7 +1273,8 @@ void SelectionBox::render(Image& zRObj) // renders into zRObj
                                 tmpHColor = tf->getBackgroundColor();
                                 tf->setBackgroundColor(msSelBgF->get(i));
                             }
-                            if (hasMsStyle(i, Style::SelectionHImage) && msSelBgB)
+                            if (hasMsStyle(i, Style::SelectionHImage)
+                                && msSelBgB)
                             {
                                 tmpHImage = tf->getBackgroundImage();
                                 tf->setBackgroundImageZ(msSelBgB->get(i));
@@ -1285,7 +1290,8 @@ void SelectionBox::render(Image& zRObj) // renders into zRObj
                                     hasMsStyle(i, Style::SelectionHAlpha));
                             }
                         }
-                        if (hasMsStyle(i, Style::SelectionBorder) && msSelBorder)
+                        if (hasMsStyle(i, Style::SelectionBorder)
+                            && msSelBorder)
                         {
                             tmpBorder = tf->getBorder();
                             tf->setBorderZ(msSelBorder->get(i));
@@ -1429,7 +1435,8 @@ void SelectionBox::render(Image& zRObj) // renders into zRObj
                             tf->setStyle(TextField::Style::Background, tmpH);
                             if (msSelBgF && msSelBgF->has(i))
                                 tf->setBackgroundColor(tmpHColor);
-                            if (hasMsStyle(i, Style::SelectionHImage) && msSelBgB)
+                            if (hasMsStyle(i, Style::SelectionHImage)
+                                && msSelBgB)
                             {
                                 tf->setBackgroundImageZ(tmpHImage);
                                 tf->setStyle(TextField::Style::BImage, tmpHB);
@@ -1438,7 +1445,8 @@ void SelectionBox::render(Image& zRObj) // renders into zRObj
                                 tf->setStyle(
                                     TextField::Style::BAlpha, tmpHAlpha);
                         }
-                        if (hasMsStyle(i, Style::SelectionBorder) && msSelBorder)
+                        if (hasMsStyle(i, Style::SelectionBorder)
+                            && msSelBorder)
                         {
                             tf->setBorderZ(tmpBorder);
                             tf->setStyle(TextField::Style::Border, tmpR);
@@ -1509,7 +1517,7 @@ void SelectionBox::render(Image& zRObj) // renders into zRObj
         }
         zRObj.releaseDrawOptions();
         zRObj.releaseDrawOptions();
-        unlockDrawable();
+        rwLock.unlockRead();
     }
 }
 
@@ -1560,7 +1568,8 @@ TextField* SelectionBox::zEntry(int i) const
     return members->z(i);
 }
 
-int SelectionBox::getSelection() const // returns the position of the selected entry
+int SelectionBox::getSelection()
+    const // returns the position of the selected entry
 {
     return selection;
 }
@@ -1695,7 +1704,8 @@ Border* SelectionBox::zSelBorder() const
     return selBorder;
 }
 
-int SelectionBox::getSelBorderColor() const // returns the selection border color
+int SelectionBox::getSelBorderColor()
+    const // returns the selection border color
 {
     if (hasStyle(Style::MultiStyled)) return 0;
     return selBorder ? selBorder->getColor() : 0;
@@ -1794,7 +1804,7 @@ AlphaField* SelectionBox::getMsSelAlphaField(
     if (!hasStyle(Style::MultiStyled)) return 0;
     if (!msSelAf) return 0;
     return msSelAf->z(i) ? dynamic_cast<AlphaField*>(msSelAf->z(i)->getThis())
-                          : 0;
+                         : 0;
 }
 
 AlphaField* SelectionBox::zMsSelAlphaField(int i) const
@@ -1867,7 +1877,8 @@ int SelectionBox::getMouseBorderWidth() const // returns the mouse border width
     return mouseBorder ? mouseBorder->getRWidth() : 0;
 }
 
-AlphaField* SelectionBox::getMouseAlphaField() const // returns the mouse AlphaField
+AlphaField*
+SelectionBox::getMouseAlphaField() const // returns the mouse AlphaField
 {
     if (hasStyle(Style::MultiStyled)) return 0;
     return mouseAf ? dynamic_cast<AlphaField*>(mouseAf->getThis()) : 0;

+ 18 - 8
Shader.cpp

@@ -4,8 +4,8 @@
 #include <d3d12.h>
 #include <iostream>
 
-#include "File.h"
 #include "DXBuffer.h"
+#include "File.h"
 #include "Text.h"
 
 using namespace Framework;
@@ -80,8 +80,10 @@ int Shader::getFirstUninitializedBufferIndex() const
     return constBuffers->getEntryCount();
 }
 
-DX11Shader::DX11Shader(ID3D11Device* device, ID3D11DeviceContext* context)
-    : Shader()
+DX11Shader::DX11Shader(
+    ID3D11Device* device, ID3D11DeviceContext* context, Critical& deviceLock)
+    : Shader(),
+      deviceLock(deviceLock)
 {
     this->device = device;
     this->context = context;
@@ -106,7 +108,9 @@ bool DX11Shader::createConstBuffer(int groesse, int index)
     while (!constBuffers->has(index))
         constBuffers->add(0);
     constBuffers->set(
-        new DX11Buffer(1, device, context, D3D11_BIND_CONSTANT_BUFFER), index);
+        new DX11Buffer(
+            1, device, context, D3D11_BIND_CONSTANT_BUFFER, deviceLock),
+        index);
     constBuffers->z(index)->setLength(groesse);
     return 1;
 }
@@ -115,8 +119,8 @@ bool DX11Shader::createConstBuffer(int groesse, int index)
 
 // Constructor
 DX11PixelShader::DX11PixelShader(
-    ID3D11Device* device, ID3D11DeviceContext* context)
-    : DX11Shader(device, context)
+    ID3D11Device* device, ID3D11DeviceContext* context, Critical& deviceLock)
+    : DX11Shader(device, context, deviceLock)
 {
     pixelShader = 0;
 }
@@ -133,7 +137,9 @@ DX11PixelShader::~DX11PixelShader()
 //  return: true if bytes is valid, false otherwise
 bool DX11PixelShader::setCompiledByteArray(unsigned char* bytes, int length)
 {
+    deviceLock.lock();
     HRESULT result = device->CreatePixelShader(bytes, length, 0, &pixelShader);
+    deviceLock.unlock();
     return result == S_OK;
 }
 
@@ -157,8 +163,8 @@ void DX11PixelShader::useShader()
 
 // Constructor
 DX11VertexShader::DX11VertexShader(
-    ID3D11Device* device, ID3D11DeviceContext* context)
-    : DX11Shader(device, context)
+    ID3D11Device* device, ID3D11DeviceContext* context, Critical& deviceLock)
+    : DX11Shader(device, context, deviceLock)
 {
     vertexShader = 0;
     inputLayout = 0;
@@ -181,8 +187,10 @@ bool DX11VertexShader::setCompiledByteArray(unsigned char* bytes, int length)
 {
     shaderByteBuffer = (unsigned char*)bytes;
     byteBufferSize = length;
+    deviceLock.lock();
     HRESULT result
         = device->CreateVertexShader(bytes, length, 0, &vertexShader);
+    deviceLock.unlock();
     return result == S_OK;
 }
 
@@ -197,8 +205,10 @@ bool DX11VertexShader::createInputLayout(
     if (!shaderByteBuffer) return 0;
     if (inputLayout) inputLayout->Release();
     inputLayout = 0;
+    deviceLock.lock();
     HRESULT res = device->CreateInputLayout(
         descArray, anz, shaderByteBuffer, byteBufferSize, &inputLayout);
+    deviceLock.unlock();
     if (res == S_OK)
     {
         shaderByteBuffer = 0;

+ 12 - 8
Shader.h

@@ -1,6 +1,7 @@
 #pragma once
 
 #include "Array.h"
+#include "Critical.h"
 
 struct ID3D10Blob;
 struct ID3D11PixelShader;
@@ -80,10 +81,12 @@ namespace Framework
     protected:
         ID3D11Device* device;
         ID3D11DeviceContext* context;
+        Critical& deviceLock;
 
     public:
-        DLLEXPORT DX11Shader(
-            ID3D11Device* device, ID3D11DeviceContext* context);
+        DLLEXPORT DX11Shader(ID3D11Device* device,
+            ID3D11DeviceContext* context,
+            Critical& deviceLock);
         DLLEXPORT virtual ~DX11Shader();
         //! Creates a constant buffer that passes constant data to the shader.
         //! A maximum of 14 buffers can be created.
@@ -92,8 +95,7 @@ namespace Framework
         //! \param index The position of the buffer in the buffer array. An
         //! existing buffer will be replaced. Buffer 1 cannot be created
         //! if buffer 0 has not been created yet, etc.
-        DLLEXPORT virtual bool createConstBuffer(
-            int size, int index) override;
+        DLLEXPORT virtual bool createConstBuffer(int size, int index) override;
     };
 
     //! Manages a pixel shader
@@ -104,8 +106,9 @@ namespace Framework
 
     public:
         //! Constructor
-        DLLEXPORT DX11PixelShader(
-            ID3D11Device* device, ID3D11DeviceContext* context);
+        DLLEXPORT DX11PixelShader(ID3D11Device* device,
+            ID3D11DeviceContext* context,
+            Critical& deviceLock);
         //! Destructor
         DLLEXPORT ~DX11PixelShader();
         //! Sets the compiled shader
@@ -132,8 +135,9 @@ namespace Framework
 
     public:
         //! Constructor
-        DLLEXPORT DX11VertexShader(
-            ID3D11Device* device, ID3D11DeviceContext* context);
+        DLLEXPORT DX11VertexShader(ID3D11Device* device,
+            ID3D11DeviceContext* context,
+            Critical& deviceLock);
         //! Destructor
         DLLEXPORT ~DX11VertexShader();
         //! Sets the compiled shader

+ 77 - 105
Table.cpp

@@ -1,11 +1,11 @@
 #include "Table.h"
 
 #include "AlphaField.h"
+#include "Border.h"
 #include "Image.h"
+#include "KeyboardEvent.h"
 #include "MouseEvent.h"
-#include "Border.h"
 #include "Scroll.h"
-#include "KeyboardEvent.h"
 #include "Text.h"
 #include "ToolTip.h"
 
@@ -123,19 +123,19 @@ void ObjTable::doMouseEvent(
     me.my -= ((vertikalScrollBar && hasStyle(Style::VScroll))
                   ? vertikalScrollBar->getScroll()
                   : 0);
-    lockDrawable();
+    rwLock.lockRead();
     if (!me.processed && !aufScroll)
     {
-        double ox
-            = getMouseColumn(me.mx
-                            + ((horizontalScrollBar && hasStyle(Style::HScroll))
-                                    ? horizontalScrollBar->getScroll()
-                                    : 0));
+        double ox = getMouseColumn(
+            me.mx
+            + ((horizontalScrollBar && hasStyle(Style::HScroll))
+                    ? horizontalScrollBar->getScroll()
+                    : 0));
         double oy
             = getMouseRow(me.my
-                           + ((vertikalScrollBar && hasStyle(Style::VScroll))
-                                   ? vertikalScrollBar->getScroll()
-                                   : 0));
+                          + ((vertikalScrollBar && hasStyle(Style::VScroll))
+                                  ? vertikalScrollBar->getScroll()
+                                  : 0));
         if (me.id == ME_RLeft)
         {
             klickSpalte = -1;
@@ -265,7 +265,7 @@ void ObjTable::doMouseEvent(
             }
         }
     }
-    unlockDrawable();
+    rwLock.unlockRead();
     me.processed = 1;
     me.mx = tmx;
     me.my = tmy;
@@ -285,7 +285,7 @@ void ObjTable::addColumn(Text* name)
 void ObjTable::addColumn(int sNum, const char* name) // insert column at sNum
 {
     if (sNum > spaltenAnzahl) return;
-    lockDrawable();
+    rwLock.lockWrite();
     members->add(new RCArray<Drawable>(), sNum);
     spaltenNamen->add(new Text(name), sNum);
     columnWidth->add(100, sNum);
@@ -303,7 +303,7 @@ void ObjTable::addColumn(int sNum, const char* name) // insert column at sNum
     }
     ++spaltenAnzahl;
     rend = 1;
-    unlockDrawable();
+    rwLock.unlockWrite();
 }
 
 void ObjTable::addColumn(int sNum, Text* name)
@@ -325,7 +325,7 @@ void ObjTable::addRow(Text* name)
 void ObjTable::addRow(int zNum, const char* name) // insert row at zNum
 {
     if (zNum > zeilenAnzahl) return;
-    lockDrawable();
+    rwLock.lockWrite();
     zeilenNamen->add(new Text(name), zNum);
     zeilenHeight->add(20, zNum);
     minZeilenHeight->add(0, zNum);
@@ -339,7 +339,7 @@ void ObjTable::addRow(int zNum, const char* name) // insert row at zNum
     }
     ++zeilenAnzahl;
     rend = 1;
-    unlockDrawable();
+    rwLock.unlockWrite();
 }
 
 void ObjTable::addRow(int zNum, Text* name)
@@ -351,7 +351,7 @@ void ObjTable::addRow(int zNum, Text* name)
 void ObjTable::removeColumn(int sNum) // delete column
 {
     if (sNum >= spaltenAnzahl) return;
-    lockDrawable();
+    rwLock.lockWrite();
     members->remove(sNum);
     spaltenNamen->remove(sNum);
     columnWidth->remove(sNum);
@@ -364,7 +364,7 @@ void ObjTable::removeColumn(int sNum) // delete column
     styles->remove(sNum);
     --spaltenAnzahl;
     rend = 1;
-    unlockDrawable();
+    rwLock.unlockWrite();
 }
 
 void ObjTable::removeColumn(const char* name)
@@ -380,7 +380,7 @@ void ObjTable::removeColumn(Text* name)
 void ObjTable::removeRow(int zNum) // delete row
 {
     if (zNum >= zeilenAnzahl) return;
-    lockDrawable();
+    rwLock.lockWrite();
     zeilenNamen->remove(zNum);
     zeilenHeight->remove(zNum);
     minZeilenHeight->remove(zNum);
@@ -394,7 +394,7 @@ void ObjTable::removeRow(int zNum) // delete row
     }
     --zeilenAnzahl;
     rend = 1;
-    unlockDrawable();
+    rwLock.unlockWrite();
 }
 
 void ObjTable::removeRow(const char* name)
@@ -427,7 +427,7 @@ void ObjTable::setColumnPosition(int sNum, int pos)
         ++delPos;
     else
         ++insertPos;
-    lockDrawable();
+    rwLock.lockWrite();
     members->add(members->get(sNum), insertPos);
     members->remove(delPos);
     spaltenNamen->add(spaltenNamen->get(sNum), insertPos);
@@ -436,8 +436,7 @@ void ObjTable::setColumnPosition(int sNum, int pos)
         columnWidth->has(sNum) ? columnWidth->get(sNum) : 0, insertPos);
     columnWidth->remove(delPos);
     minSpaltenWidth->add(
-        minSpaltenWidth->has(sNum) ? minSpaltenWidth->get(sNum) : 0,
-        insertPos);
+        minSpaltenWidth->has(sNum) ? minSpaltenWidth->get(sNum) : 0, insertPos);
     minSpaltenWidth->remove(delPos);
     msaRam->add(msaRam->z(sNum), insertPos);
     msaRam->remove(delPos);
@@ -446,7 +445,7 @@ void ObjTable::setColumnPosition(int sNum, int pos)
     styles->add(styles->get(sNum), insertPos);
     styles->remove(delPos);
     rend = 1;
-    unlockDrawable();
+    rwLock.unlockWrite();
 }
 
 void ObjTable::setRowPosition(
@@ -469,7 +468,7 @@ void ObjTable::setRowPosition(int zNum, int pos)
         ++delPos;
     else
         ++insertPos;
-    lockDrawable();
+    rwLock.lockWrite();
     zeilenNamen->add(zeilenNamen->get(zNum), insertPos);
     zeilenNamen->remove(delPos);
     zeilenHeight->add(
@@ -511,14 +510,13 @@ void ObjTable::setRowPosition(int zNum, int pos)
         }
     }
     rend = 1;
-    unlockDrawable();
+    rwLock.unlockWrite();
 }
 
-void ObjTable::setDrawableZ(
-    int sNum, int zNum, Drawable* obj) // sets a drawing
+void ObjTable::setDrawableZ(int sNum, int zNum, Drawable* obj) // sets a drawing
 {
     if (sNum >= spaltenAnzahl || zNum >= zeilenAnzahl) return;
-    lockDrawable();
+    rwLock.lockWrite();
     if (!members->z(sNum)) members->set(new RCArray<Drawable>(), sNum);
     while (members->z(sNum)->getEntryCount() <= zNum)
         members->z(sNum)->add(0);
@@ -532,7 +530,7 @@ void ObjTable::setDrawableZ(
         obj->setHeight(zeilenHeight->get(zNum));
     }
     rend = 1;
-    unlockDrawable();
+    rwLock.unlockWrite();
 }
 
 void ObjTable::setDrawableZ(
@@ -552,10 +550,10 @@ void ObjTable::setDrawableZ(
 void ObjTable::setColumnWidth(int sNum, int br) // sets the column width
 {
     if (sNum >= spaltenAnzahl) return;
-    lockDrawable();
+    rwLock.lockWrite();
     columnWidth->set(br, sNum);
     rend = 1;
-    unlockDrawable();
+    rwLock.unlockWrite();
 }
 
 void ObjTable::setColumnWidth(const char* name, int br)
@@ -571,10 +569,10 @@ void ObjTable::setColumnWidth(Text* name, int br)
 void ObjTable::setRowHeight(int zNum, int hi) // sets the row height
 {
     if (zNum >= zeilenAnzahl) return;
-    lockDrawable();
+    rwLock.lockWrite();
     zeilenHeight->set(hi, zNum);
     rend = 1;
-    unlockDrawable();
+    rwLock.unlockWrite();
 }
 
 void ObjTable::setRowHeight(const char* name, int hi)
@@ -591,10 +589,10 @@ void ObjTable::setMinColumnWidth(
     int sNum, int minBr) // sets the minimum column width
 {
     if (sNum >= spaltenAnzahl) return;
-    lockDrawable();
+    rwLock.lockWrite();
     minSpaltenWidth->set(minBr, sNum);
     rend = 1;
-    unlockDrawable();
+    rwLock.unlockWrite();
 }
 
 void ObjTable::setMinColumnWidth(const char* name, int minBr)
@@ -611,10 +609,10 @@ void ObjTable::setMaxColumnWidth(
     int sNum, int maxBr) // sets the maximum column width
 {
     if (sNum >= spaltenAnzahl) return;
-    lockDrawable();
+    rwLock.lockWrite();
     maxSpaltenWidth->set(maxBr, sNum);
     rend = 1;
-    unlockDrawable();
+    rwLock.unlockWrite();
 }
 
 void ObjTable::setMaxColumnWidth(const char* name, int maxBr)
@@ -631,10 +629,10 @@ void ObjTable::setMinRowHeight(
     int zNum, int minHi) // sets the minimum row height
 {
     if (zNum >= zeilenAnzahl) return;
-    lockDrawable();
+    rwLock.lockWrite();
     minZeilenHeight->set(minHi, zNum);
     rend = 1;
-    unlockDrawable();
+    rwLock.unlockWrite();
 }
 
 void ObjTable::setMinRowHeight(const char* name, int minHi)
@@ -651,10 +649,10 @@ void ObjTable::setMaxRowHeight(
     int zNum, int maxHi) // sets the maximum row height
 {
     if (zNum >= zeilenAnzahl) return;
-    lockDrawable();
+    rwLock.lockWrite();
     maxZeilenHeight->set(maxHi, zNum);
     rend = 1;
-    unlockDrawable();
+    rwLock.unlockWrite();
 }
 
 void ObjTable::setMaxRowHeight(const char* name, int maxHi)
@@ -671,11 +669,11 @@ void ObjTable::setSelection(
     int sNum, int zNum) // selects the corresponding field
 {
     if (sNum >= spaltenAnzahl || zNum >= zeilenAnzahl) return;
-    lockDrawable();
+    rwLock.lockWrite();
     selected.x = sNum;
     selected.y = zNum;
     rend = 1;
-    unlockDrawable();
+    rwLock.unlockWrite();
 }
 
 void ObjTable::setSelection(const char* spaltenName, const char* zeilenName)
@@ -753,14 +751,12 @@ void ObjTable::setABorderZ(
 void ObjTable::setABorderZ(
     const char* spaltenName, const char* zeilenName, Border* ram)
 {
-    setABorderZ(
-        getColumnNumber(spaltenName), getRowNumber(zeilenName), ram);
+    setABorderZ(getColumnNumber(spaltenName), getRowNumber(zeilenName), ram);
 }
 
 void ObjTable::setABorderZ(Text* spaltenName, Text* zeilenName, Border* ram)
 {
-    setABorderZ(
-        getColumnNumber(spaltenName), getRowNumber(zeilenName), ram);
+    setABorderZ(getColumnNumber(spaltenName), getRowNumber(zeilenName), ram);
 }
 
 void ObjTable::setARColor(
@@ -827,15 +823,13 @@ void ObjTable::setAAlphaFieldZ(
 void ObjTable::setAAlphaFieldZ(
     const char* spaltenName, const char* zeilenName, AlphaField* af)
 {
-    setAAlphaFieldZ(
-        getColumnNumber(spaltenName), getRowNumber(zeilenName), af);
+    setAAlphaFieldZ(getColumnNumber(spaltenName), getRowNumber(zeilenName), af);
 }
 
 void ObjTable::setAAlphaFieldZ(
     Text* spaltenName, Text* zeilenName, AlphaField* af)
 {
-    setAAlphaFieldZ(
-        getColumnNumber(spaltenName), getRowNumber(zeilenName), af);
+    setAAlphaFieldZ(getColumnNumber(spaltenName), getRowNumber(zeilenName), af);
 }
 
 void ObjTable::setAAfColor(
@@ -884,14 +878,12 @@ void ObjTable::setAAfStrength(
 void ObjTable::setAAfStrength(
     const char* spaltenName, const char* zeilenName, int st)
 {
-    setAAfStrength(
-        getColumnNumber(spaltenName), getRowNumber(zeilenName), st);
+    setAAfStrength(getColumnNumber(spaltenName), getRowNumber(zeilenName), st);
 }
 
 void ObjTable::setAAfStrength(Text* spaltenName, Text* zeilenName, int st)
 {
-    setAAfStrength(
-        getColumnNumber(spaltenName), getRowNumber(zeilenName), st);
+    setAAfStrength(getColumnNumber(spaltenName), getRowNumber(zeilenName), st);
 }
 
 void ObjTable::addMsStyle(
@@ -909,14 +901,12 @@ void ObjTable::addMsStyle(
 void ObjTable::addMsStyle(
     const char* spaltenName, const char* zeilenName, __int64 style)
 {
-    addMsStyle(
-        getColumnNumber(spaltenName), getRowNumber(zeilenName), style);
+    addMsStyle(getColumnNumber(spaltenName), getRowNumber(zeilenName), style);
 }
 
 void ObjTable::addMsStyle(Text* spaltenName, Text* zeilenName, __int64 style)
 {
-    addMsStyle(
-        getColumnNumber(spaltenName), getRowNumber(zeilenName), style);
+    addMsStyle(getColumnNumber(spaltenName), getRowNumber(zeilenName), style);
 }
 
 void ObjTable::setMsStyle(int sNum, int zNum, __int64 style)
@@ -929,14 +919,12 @@ void ObjTable::setMsStyle(int sNum, int zNum, __int64 style)
 void ObjTable::setMsStyle(
     const char* spaltenName, const char* zeilenName, __int64 style)
 {
-    setMsStyle(
-        getColumnNumber(spaltenName), getRowNumber(zeilenName), style);
+    setMsStyle(getColumnNumber(spaltenName), getRowNumber(zeilenName), style);
 }
 
 void ObjTable::setMsStyle(Text* spaltenName, Text* zeilenName, __int64 style)
 {
-    setMsStyle(
-        getColumnNumber(spaltenName), getRowNumber(zeilenName), style);
+    setMsStyle(getColumnNumber(spaltenName), getRowNumber(zeilenName), style);
 }
 
 void ObjTable::setMsStyle(int sNum, int zNum, __int64 style, bool add_remove)
@@ -996,8 +984,7 @@ void ObjTable::removeMsStyle(
         getColumnNumber(spaltenName), getRowNumber(zeilenName), style);
 }
 
-void ObjTable::removeMsStyle(
-    Text* spaltenName, Text* zeilenName, __int64 style)
+void ObjTable::removeMsStyle(Text* spaltenName, Text* zeilenName, __int64 style)
 {
     removeMsStyle(
         getColumnNumber(spaltenName), getRowNumber(zeilenName), style);
@@ -1005,7 +992,7 @@ void ObjTable::removeMsStyle(
 
 bool ObjTable::tick(double tickVal) // tick Message
 {
-    lockDrawable();
+    rwLock.lockRead();
     for (int i = 0; i < zeilenAnzahl; ++i)
     {
         for (int j = 0; j < spaltenAnzahl; ++j)
@@ -1014,7 +1001,7 @@ bool ObjTable::tick(double tickVal) // tick Message
             if (obj) rend |= obj->tick(tickVal);
         }
     }
-    unlockDrawable();
+    rwLock.unlockRead();
     return DrawableBackground::tick(tickVal);
 }
 
@@ -1026,7 +1013,7 @@ void ObjTable::doKeyboardEvent(KeyboardEvent& te)
         return;
     if (tak && (te.processed || tak(takParam, this, te)))
     {
-        lockDrawable();
+        rwLock.lockRead();
         if (zDrawable(selected.x, selected.y))
         {
             zDrawable(selected.x, selected.y)->doKeyboardEvent(te);
@@ -1054,21 +1041,20 @@ void ObjTable::doKeyboardEvent(KeyboardEvent& te)
                 }
             }
         }
-        unlockDrawable();
+        rwLock.unlockRead();
     }
     te.processed = 1;
-    if (ntakc && te.processed && nTak)
-        te.processed = nTak(ntakParam, this, te);
+    if (ntakc && te.processed && nTak) te.processed = nTak(ntakParam, this, te);
 }
 
 void ObjTable::render(Image& zRObj) // renders the table into zRObj
 {
     if (hasStyleNot(Style::Visible)) return;
     DrawableBackground::render(zRObj);
-    lockDrawable();
+    rwLock.lockRead();
     if (!zRObj.setDrawOptions(innenPosition, innenSize))
     {
-        unlockDrawable();
+        rwLock.unlockRead();
         return;
     }
     int xPos = 0;
@@ -1103,8 +1089,7 @@ void ObjTable::render(Image& zRObj) // renders the table into zRObj
                     zRObj.drawLineHAlpha(
                         xPos, yPos + zHi + i, sBr, rasterColor);
             }
-            Drawable* obj
-                = tmp_zDrawables->has(z) ? tmp_zDrawables->z(z) : 0;
+            Drawable* obj = tmp_zDrawables->has(z) ? tmp_zDrawables->z(z) : 0;
             if (obj)
             {
                 obj->setPosition(xPos, yPos);
@@ -1122,8 +1107,8 @@ void ObjTable::render(Image& zRObj) // renders the table into zRObj
                         tmp_aAf = getAAlphaField(s, z);
                         aRamB = hasMsStyle(s, z, Style::SelectionBorder)
                              && tmp_aRam;
-                        aAfB
-                            = hasMsStyle(s, z, Style::SelectionBuffer) && tmp_aAf;
+                        aAfB = hasMsStyle(s, z, Style::SelectionBuffer)
+                            && tmp_aAf;
                     }
                     int aRbr = 0;
                     if (aRamB)
@@ -1155,7 +1140,7 @@ void ObjTable::render(Image& zRObj) // renders the table into zRObj
         horizontalScrollBar->getScrollData()->max
             = xPos + horizontalScrollBar->getScroll();
     zRObj.releaseDrawOptions();
-    unlockDrawable();
+    rwLock.unlockRead();
 }
 
 // constant
@@ -1252,14 +1237,12 @@ Drawable* ObjTable::zDrawable(
 Drawable* ObjTable::zDrawable(
     const char* spaltenName, const char* zeilenName) const
 {
-    return zDrawable(
-        getColumnNumber(spaltenName), getRowNumber(zeilenName));
+    return zDrawable(getColumnNumber(spaltenName), getRowNumber(zeilenName));
 }
 
 Drawable* ObjTable::zDrawable(Text* spaltenName, Text* zeilenName) const
 {
-    return zDrawable(
-        getColumnNumber(spaltenName), getRowNumber(zeilenName));
+    return zDrawable(getColumnNumber(spaltenName), getRowNumber(zeilenName));
 }
 
 Drawable* ObjTable::getDrawable(
@@ -1274,18 +1257,15 @@ Drawable* ObjTable::getDrawable(
 Drawable* ObjTable::getDrawable(
     const char* spaltenName, const char* zeilenName) const
 {
-    return getDrawable(
-        getColumnNumber(spaltenName), getRowNumber(zeilenName));
+    return getDrawable(getColumnNumber(spaltenName), getRowNumber(zeilenName));
 }
 
 Drawable* ObjTable::getDrawable(Text* spaltenName, Text* zeilenName) const
 {
-    return getDrawable(
-        getColumnNumber(spaltenName), getRowNumber(zeilenName));
+    return getDrawable(getColumnNumber(spaltenName), getRowNumber(zeilenName));
 }
 
-int ObjTable::getColumnWidth(
-    int num) const // returns the width of the column
+int ObjTable::getColumnWidth(int num) const // returns the width of the column
 {
     return columnWidth->get(num);
 }
@@ -1347,8 +1327,7 @@ int ObjTable::getMaxColumnWidth(Text* name) const
     return getMaxColumnWidth(getColumnNumber(name));
 }
 
-int ObjTable::getMinRowHeight(
-    int num) const // returns the minimum row height
+int ObjTable::getMinRowHeight(int num) const // returns the minimum row height
 {
     return minZeilenHeight->get(num);
 }
@@ -1363,8 +1342,7 @@ int ObjTable::getMinRowHeight(Text* name) const
     return getMinRowHeight(getRowNumber(name));
 }
 
-int ObjTable::getMaxRowHeight(
-    int num) const // returns the maximum row height
+int ObjTable::getMaxRowHeight(int num) const // returns the maximum row height
 {
     return maxZeilenHeight->get(num);
 }
@@ -1413,8 +1391,7 @@ Text* ObjTable::zMouseColumnName(int mx) const
     return zColumnName((int)tmp);
 }
 
-double ObjTable::getMouseRow(
-    int my) const // calculates the row under the mouse
+double ObjTable::getMouseRow(int my) const // calculates the row under the mouse
 {
     if (my >= gr.y) return -1;
     if (my < 0) return -1;
@@ -1511,8 +1488,7 @@ AlphaField* ObjTable::zAAlphaField(int sNum, int zNum) const
 Border* ObjTable::getABorder(const char* spaltenName,
     const char* zeilenName) const // returns the selection border
 {
-    return getABorder(
-        getColumnNumber(spaltenName), getRowNumber(zeilenName));
+    return getABorder(getColumnNumber(spaltenName), getRowNumber(zeilenName));
 }
 
 Border* ObjTable::zABorder(
@@ -1531,15 +1507,13 @@ AlphaField* ObjTable::getAAlphaField(const char* spaltenName,
 AlphaField* ObjTable::zAAlphaField(
     const char* spaltenName, const char* zeilenName) const
 {
-    return zAAlphaField(
-        getColumnNumber(spaltenName), getRowNumber(zeilenName));
+    return zAAlphaField(getColumnNumber(spaltenName), getRowNumber(zeilenName));
 }
 
 Border* ObjTable::getABorder(
     Text* spaltenName, Text* zeilenName) const // returns the selection border
 {
-    return getABorder(
-        getColumnNumber(spaltenName), getRowNumber(zeilenName));
+    return getABorder(getColumnNumber(spaltenName), getRowNumber(zeilenName));
 }
 
 Border* ObjTable::zABorder(Text* spaltenName, Text* zeilenName) const
@@ -1556,8 +1530,7 @@ AlphaField* ObjTable::getAAlphaField(Text* spaltenName,
 
 AlphaField* ObjTable::zAAlphaField(Text* spaltenName, Text* zeilenName) const
 {
-    return zAAlphaField(
-        getColumnNumber(spaltenName), getRowNumber(zeilenName));
+    return zAAlphaField(getColumnNumber(spaltenName), getRowNumber(zeilenName));
 }
 
 bool ObjTable::hasMsStyle(
@@ -1636,8 +1609,7 @@ Drawable* ObjTable::duplicate() const // Creates a copy of the table
     for (int s = 0; s < spaltenAnzahl; ++s)
     {
         obj->addColumn(spaltenNamen->get(s));
-        if (columnWidth->has(s))
-            obj->setColumnWidth(s, columnWidth->get(s));
+        if (columnWidth->has(s)) obj->setColumnWidth(s, columnWidth->get(s));
         if (minSpaltenWidth->has(s))
             obj->setMinColumnWidth(s, minSpaltenWidth->get(s));
         if (maxSpaltenWidth->has(s))

+ 40 - 48
TextField.cpp

@@ -3,16 +3,16 @@
 #include <math.h>
 
 #include "AlphaField.h"
-#include "Image.h"
-#include "Window.h"
-#include "Globals.h"
-#include "MouseEvent.h"
 #include "Border.h"
 #include "Font.h"
-#include "Scroll.h"
+#include "Globals.h"
+#include "Image.h"
 #include "KeyboardEvent.h"
+#include "MouseEvent.h"
+#include "Scroll.h"
 #include "Text.h"
 #include "ToolTip.h"
+#include "Window.h"
 
 using namespace Framework;
 
@@ -514,36 +514,36 @@ void TextField::setCharEvent(
 
 void TextField::setText(Text* txt) // sets the displayed text
 {
-    lockDrawable();
+    rwLock.lockWrite();
     if (!tm->text) tm->text = new Text();
     tm->text->setText(*txt);
     if (hasStyle(Style::VScroll)) updateVScroll();
     if (hasStyle(Style::HScroll)) updateHScroll();
-    unlockDrawable();
+    rwLock.unlockWrite();
     rend = 1;
     txt->release();
 }
 
 void TextField::setTextZ(Text* txt) // sets a pointer to the displayed text
 {
-    lockDrawable();
+    rwLock.lockWrite();
     if (tm->text) tm->text->release();
     tm->text = txt;
     if (hasStyle(Style::VScroll)) updateVScroll();
     if (hasStyle(Style::HScroll)) updateHScroll();
     rend = 1;
-    unlockDrawable();
+    rwLock.unlockWrite();
 }
 
 void TextField::setText(const char* txt) // sets the displayed text
 {
-    lockDrawable();
+    rwLock.lockWrite();
     if (!tm->text) tm->text = new Text();
     tm->text->setText(txt);
     if (hasStyle(Style::VScroll)) updateVScroll();
     if (hasStyle(Style::HScroll)) updateHScroll();
     rend = 1;
-    unlockDrawable();
+    rwLock.unlockWrite();
 }
 
 // sets the text with styles
@@ -567,7 +567,7 @@ void TextField::setText(const char* txt) // sets the displayed text
 //              FFFFFFFF is an 8-digit hex value
 void TextField::setFormattedText(const char* txt)
 {
-    lockDrawable();
+    rwLock.lockWrite();
     if (!tm->text) tm->text = new Text();
     tm->textStyle.clear();
     TextStyle current;
@@ -663,7 +663,7 @@ void TextField::setFormattedText(const char* txt)
     if (hasStyle(Style::VScroll)) updateVScroll();
     if (hasStyle(Style::HScroll)) updateHScroll();
     rend = 1;
-    unlockDrawable();
+    rwLock.unlockWrite();
 }
 
 // inserts line breaks so that the text does not exceed the width of the text
@@ -814,8 +814,7 @@ void TextField::addRow(const char* zeile) // appends a line
         Text* txt = new Text(zeile);
         if (zeile[txt->getLength() - 1] != '\n') txt->append("\n");
         TextRenderer* r = tm->renderer->z(0);
-        if (tm->textStyle.get(tm->textStyle.getEntryCount() - 1)
-                .rendererIndex
+        if (tm->textStyle.get(tm->textStyle.getEntryCount() - 1).rendererIndex
             < tm->renderer->getEntryCount())
             r = tm->renderer->z(
                 tm->textStyle.get(tm->textStyle.getEntryCount() - 1)
@@ -823,16 +822,15 @@ void TextField::addRow(const char* zeile) // appends a line
         if (r)
         {
             bool vs = vertikalScrollBar && hasStyle(Style::VScroll);
-            int rbr = (border && hasStyle(Style::Border)) ? border->getRWidth()
-                                                          : 0;
+            int rbr
+                = (border && hasStyle(Style::Border)) ? border->getRWidth() : 0;
             r->setFontSize(
-                tm->textStyle.get(tm->textStyle.getEntryCount() - 1)
-                    .fontSize);
+                tm->textStyle.get(tm->textStyle.getEntryCount() - 1).fontSize);
             r->formatText(txt, gr.x - ((int)vs * 15) - rbr * 2);
         }
-        lockDrawable();
+        rwLock.lockWrite();
         tm->text->append(txt->getText());
-        unlockDrawable();
+        rwLock.unlockWrite();
         txt->release();
         if (hasStyle(Style::VScroll)) updateVScroll();
         if (hasStyle(Style::HScroll)) updateHScroll();
@@ -850,8 +848,7 @@ void TextField::addRow(const char* zeile, int color)
         Text* txt = new Text(zeile);
         if (zeile[txt->getLength() - 1] != '\n') txt->append("\n");
         TextRenderer* r = tm->renderer->z(0);
-        if (tm->textStyle.get(tm->textStyle.getEntryCount() - 1)
-                .rendererIndex
+        if (tm->textStyle.get(tm->textStyle.getEntryCount() - 1).rendererIndex
             < tm->renderer->getEntryCount())
             r = tm->renderer->z(
                 tm->textStyle.get(tm->textStyle.getEntryCount() - 1)
@@ -859,19 +856,18 @@ void TextField::addRow(const char* zeile, int color)
         if (r)
         {
             bool vs = vertikalScrollBar && hasStyle(Style::VScroll);
-            int rbr = (border && hasStyle(Style::Border)) ? border->getRWidth()
-                                                          : 0;
+            int rbr
+                = (border && hasStyle(Style::Border)) ? border->getRWidth() : 0;
             r->setFontSize(
-                tm->textStyle.get(tm->textStyle.getEntryCount() - 1)
-                    .fontSize);
+                tm->textStyle.get(tm->textStyle.getEntryCount() - 1).fontSize);
             r->formatText(txt, gr.x - ((int)vs * 15) - rbr * 2);
         }
-        lockDrawable();
+        rwLock.lockWrite();
         tm->text->append(txt->getText());
         setFontColor(tm->text->getLength() - txt->getLength(),
             tm->text->getLength(),
             color);
-        unlockDrawable();
+        rwLock.unlockWrite();
         txt->release();
         if (hasStyle(Style::VScroll)) updateVScroll();
         if (hasStyle(Style::HScroll)) updateHScroll();
@@ -1066,7 +1062,7 @@ void TextField::setVScrollToRow(int zeile) // scrolls to line
     if (vertikalScrollBar && tm->renderer && tm->renderer->getEntryCount()
         && tm->text && hasStyle(Style::Multiline))
     {
-        lockDrawable();
+        rwLock.lockWrite();
         tm->resetIteration();
         int len = tm->text->getLength();
         int y = 0;
@@ -1099,7 +1095,7 @@ void TextField::setVScrollToRow(int zeile) // scrolls to line
             }
             tm->nextStyle();
         }
-        unlockDrawable();
+        rwLock.unlockWrite();
         vertikalScrollBar->scroll(y);
         rend = 1;
     }
@@ -1121,7 +1117,7 @@ void TextField::updateVScroll(int pos) // scrolls down
                 hi -= border->getRWidth() * 2;
             if (hasStyle(Style::HScroll) && horizontalScrollBar) hi -= 15;
             int th = 0;
-            lockDrawable();
+            rwLock.lockWrite();
             tm->resetIteration();
             int len = tm->text->getLength();
             const char* text = tm->text->getText();
@@ -1165,7 +1161,7 @@ void TextField::updateVScroll(int pos) // scrolls down
                 lastMax = max;
             }
             th += lastMax;
-            unlockDrawable();
+            rwLock.unlockWrite();
             vertikalScrollBar->update(th, hi);
         }
         if (sPos - sPosZH < vertikalScrollBar->getScroll())
@@ -1180,7 +1176,7 @@ void TextField::updateVScroll(int pos) // scrolls down
 void TextField::updateHScroll(int pos) // scrolls to cursor position
 {
     if (pos == -1) pos = cpos;
-    lockDrawable();
+    rwLock.lockWrite();
     if (horizontalScrollBar && tm->text && tm->renderer)
     {
         if (hasStyleNot(Style::Multiline)) tm->text->remove('\n');
@@ -1220,7 +1216,7 @@ void TextField::updateHScroll(int pos) // scrolls to cursor position
         if (cbr < horizontalScrollBar->getScroll())
             horizontalScrollBar->scroll(cbr);
     }
-    unlockDrawable();
+    rwLock.unlockWrite();
 }
 
 // Returns the width in pixels needed to fully display the current text with
@@ -1228,9 +1224,9 @@ void TextField::updateHScroll(int pos) // scrolls to cursor position
 int TextField::getNeededWidth()
 {
     int maxBr = 0;
-    lockDrawable();
+    rwLock.lockRead();
     if (tm->text && tm->renderer) maxBr = getTextWidth();
-    unlockDrawable();
+    rwLock.unlockRead();
     bool vs = vertikalScrollBar && hasStyle(Style::VScroll);
     bool r = border && hasStyle(Style::Border);
     return maxBr + (r ? border->getRWidth() * 2 : 0) + (vs ? 15 : 0);
@@ -1241,9 +1237,9 @@ int TextField::getNeededWidth()
 int TextField::getNeededHeight()
 {
     int th = 0;
-    lockDrawable();
+    rwLock.lockRead();
     if (tm->text && tm->renderer) th = getTextHeight();
-    unlockDrawable();
+    rwLock.unlockRead();
     bool hs = horizontalScrollBar && hasStyle(Style::HScroll);
     bool r = border && hasStyle(Style::Border);
     return th + (r ? border->getRWidth() * 2 : 0) + (hs ? 15 : 0);
@@ -1478,8 +1474,7 @@ void TextField::doKeyboardEvent(KeyboardEvent& te)
         if (hasStyle(Style::HScroll)) updateHScroll(cpos);
         te.processed = 1;
     }
-    if (ntakc && te.processed && nTak)
-        te.processed = nTak(ntakParam, this, te);
+    if (ntakc && te.processed && nTak) te.processed = nTak(ntakParam, this, te);
     release();
 }
 
@@ -1488,10 +1483,10 @@ void TextField::render(Image& zRObj) // draws to zRObj
     if (hasStyleNot(Style::Visible)) return;
     DrawableBackground::render(zRObj);
     if (!tm->text || !tm->renderer) return;
-    lockDrawable();
+    rwLock.lockRead();
     if (!zRObj.setDrawOptions(innenPosition, innenSize))
     {
-        unlockDrawable();
+        rwLock.unlockRead();
         return;
     }
     if (hasStyleNot(Style::Multiline)) tm->text->remove('\n');
@@ -1518,7 +1513,6 @@ void TextField::render(Image& zRObj) // draws to zRObj
         text = txtWithLineBreaks;
         len = txtWithLineBreaks.getLength();
     }
-    lockDrawable();
     tm->resetIteration();
     if (thi == 0)
     {
@@ -1563,9 +1557,8 @@ void TextField::render(Image& zRObj) // draws to zRObj
         }
         tm->nextStyle();
     }
-    unlockDrawable();
     zRObj.releaseDrawOptions();
-    unlockDrawable();
+    rwLock.unlockRead();
 }
 
 // Constant
@@ -1586,8 +1579,7 @@ Font* TextField::getFont() const // returns the font
     return tm->zCurrentRenderer() ? tm->zCurrentRenderer()->getFont() : 0;
 }
 
-Font*
-TextField::zFont() const // returns the font without reference counter
+Font* TextField::zFont() const // returns the font without reference counter
 {
     tm->resetIteration();
     return tm->zCurrentRenderer() ? tm->zCurrentRenderer()->zFont() : 0;

+ 10 - 2
Texture.cpp

@@ -84,14 +84,16 @@ bool DX9Texture::needsUpdate() const
     return 0;
 }
 
-DX11Texture::DX11Texture(ID3D11Device* device, ID3D11DeviceContext* context)
+DX11Texture::DX11Texture(
+    ID3D11Device* device, ID3D11DeviceContext* context, Critical& deviceLock)
     : Texture(),
       txt(0),
       view(0),
       device(device),
       context(context),
       renderTarget(0),
-      useMips(1)
+      useMips(1),
+      deviceLock(deviceLock)
 {}
 
 DX11Texture::~DX11Texture()
@@ -128,7 +130,9 @@ bool DX11Texture::updateTextur()
         bufferDesc.Usage = renderTarget || useMips ? D3D11_USAGE_DEFAULT
                                                    : D3D11_USAGE_DYNAMIC;
         bufferDesc.MiscFlags = useMips ? D3D11_RESOURCE_MISC_GENERATE_MIPS : 0;
+        deviceLock.lock();
         HRESULT r = device->CreateTexture2D(&bufferDesc, 0, &txt);
+        deviceLock.unlock();
         if (r != S_OK) return 0;
     }
     if (!renderTarget && (bild->getNeedRender() || changed))
@@ -167,7 +171,9 @@ bool DX11Texture::updateTextur()
         resourceDesk.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
         resourceDesk.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
         resourceDesk.Texture2D.MipLevels = useMips ? -1 : 1;
+        deviceLock.lock();
         HRESULT r = device->CreateShaderResourceView(txt, &resourceDesk, &view);
+        deviceLock.unlock();
         if (r != S_OK) return 0;
         if (context && useMips) context->GenerateMips(view);
     }
@@ -223,7 +229,9 @@ void DX11Texture::copyToImage(Image* zB)
     tempBufferDesc.MipLevels = 1;
     tempBufferDesc.Usage = D3D11_USAGE_STAGING;
     ID3D11Texture2D* tmpTxt;
+    deviceLock.lock();
     HRESULT r = device->CreateTexture2D(&tempBufferDesc, 0, &tmpTxt);
+    deviceLock.unlock();
     if (r != S_OK) throw "could not create resource copy with cpu read access";
     context->CopyResource(tmpTxt, txt);
     zB->newImage(bild->getWidth(), bild->getHeight(), 0);

+ 6 - 3
Texture.h

@@ -1,5 +1,6 @@
 #pragma once
 
+#include "Critical.h"
 #include "Point.h"
 #include "ReferenceCounter.h"
 
@@ -11,7 +12,7 @@ struct ID3D11DeviceContext;
 namespace Framework
 {
     class Image;       //! Image.h
-    class Render3D;   //! Render3D.h
+    class Render3D;    //! Render3D.h
     class TextureList; //! TextureList.h
     class DX12CopyCommandQueue;
     class DX12DirectCommandQueue;
@@ -74,10 +75,12 @@ namespace Framework
         ID3D11DeviceContext* context;
         bool renderTarget;
         bool useMips;
+        Critical& deviceLock;
 
     public:
-        DLLEXPORT DX11Texture(
-            ID3D11Device* device, ID3D11DeviceContext* context);
+        DLLEXPORT DX11Texture(ID3D11Device* device,
+            ID3D11DeviceContext* context,
+            Critical& deviceLock);
         DLLEXPORT ~DX11Texture();
         //! Updates the texture. The pixels of the current image are copied
         //! to graphics memory

+ 2 - 2
Texture2D.cpp

@@ -95,7 +95,7 @@ bool Texture2D::tick(double t)
         a->compensation += t;
         int tmp = a->now;
         int tmp2 = animationIndex;
-        a->data->lock();
+        a->data->readLock().lock();
         if (a->compensation >= 1.0 / a->data->getFPS())
         {
             a->compensation -= 1.0 / a->data->getFPS();
@@ -105,7 +105,7 @@ bool Texture2D::tick(double t)
                 if (!a->data->isRepeating()) nextAnimation();
             }
         }
-        a->data->unlock();
+        a->data->readLock().unlock();
         if (tmp != a->now || tmp2 != animationIndex) return 1;
     }
     return 0;

+ 33 - 43
TextureList.cpp

@@ -5,13 +5,11 @@
 
 using namespace Framework;
 
-int TextureList::id = 0;
-Critical TextureList::cs;
-
 // Contents of the TextureList class
 // Constructor
 TextureList::TextureList()
-    : ReferenceCounter()
+    : ReferenceCounter(),
+      nextId(0)
 {
     textures = new RCArray<Texture>();
     names = new RCArray<Text>();
@@ -27,10 +25,10 @@ TextureList::~TextureList()
 // Deletes all textures
 __declspec(dllexport) void TextureList::clear()
 {
-    cs.lock();
+    lock.lockWrite();
     textures->clear();
     names->clear();
-    cs.unlock();
+    lock.unlockWrite();
 }
 
 // Adds a texture to the list
@@ -38,20 +36,20 @@ __declspec(dllexport) void TextureList::clear()
 //  name: The name under which the texture is stored in the list
 bool TextureList::addTexture(Texture* t, const char* name)
 {
-    cs.lock();
+    lock.lockWrite();
     for (auto i : *names)
     {
         if (i->isEqual(name))
         {
             t->release();
-            cs.unlock();
+            lock.unlockWrite();
             return 0;
         }
     }
-    t->id = id++;
+    t->id = nextId++;
     textures->add(t);
     names->add(new Text(name));
-    cs.unlock();
+    lock.unlockWrite();
     return 1;
 }
 
@@ -59,7 +57,7 @@ bool TextureList::addTexture(Texture* t, const char* name)
 //  name: The name of the texture
 void TextureList::removeTexture(const char* name)
 {
-    cs.lock();
+    lock.lockWrite();
     int index = 0;
     for (auto i : *names)
     {
@@ -67,12 +65,12 @@ void TextureList::removeTexture(const char* name)
         {
             names->remove(index);
             textures->remove(index);
-            cs.unlock();
+            lock.unlockWrite();
             return;
         }
         index++;
     }
-    cs.unlock();
+    lock.unlockWrite();
 }
 
 // Checks whether a texture has been stored under a specific name
@@ -80,16 +78,16 @@ void TextureList::removeTexture(const char* name)
 //  return: true if a texture with the name exists
 bool TextureList::hasTexture(const char* name) const
 {
-    cs.lock();
+    lock.lockRead();
     for (auto i : *names)
     {
         if (i->isEqual(name))
         {
-            cs.unlock();
+            lock.unlockRead();
             return 1;
         }
     }
-    cs.unlock();
+    lock.unlockRead();
     return 0;
 }
 
@@ -97,18 +95,19 @@ bool TextureList::hasTexture(const char* name) const
 //  name: The name of the texture
 Texture* TextureList::getTexture(const char* name) const
 {
-    cs.lock();
+    lock.lockRead();
     int index = 0;
     for (auto i : *names)
     {
         if (i->isEqual(name))
         {
-            cs.unlock();
-            return textures->get(index);
+            Texture* result = textures->get(index);
+            lock.unlockRead();
+            return result;
         }
         index++;
     }
-    cs.unlock();
+    lock.unlockRead();
     return 0;
 }
 
@@ -116,16 +115,17 @@ Texture* TextureList::getTexture(const char* name) const
 //  id: The id of the texture
 Texture* TextureList::getTexture(int id) const
 {
-    cs.lock();
+    lock.lockRead();
     for (auto i : *textures)
     {
         if (i->getId() == id)
         {
-            cs.unlock();
-            return dynamic_cast<Texture*>(i->getThis());
+            Texture* result = dynamic_cast<Texture*>(i->getThis());
+            lock.unlockRead();
+            return result;
         }
     }
-    cs.unlock();
+    lock.unlockRead();
     return 0;
 }
 
@@ -133,18 +133,19 @@ Texture* TextureList::getTexture(int id) const
 //  name: The name of the texture
 Texture* TextureList::zTexture(const char* name) const
 {
-    cs.lock();
+    lock.lockRead();
     int index = 0;
     for (auto i : *names)
     {
         if (i->isEqual(name))
         {
-            cs.unlock();
-            return textures->z(index);
+            Texture* result = textures->z(index);
+            lock.unlockRead();
+            return result;
         }
         index++;
     }
-    cs.unlock();
+    lock.unlockRead();
     return 0;
 }
 
@@ -152,26 +153,15 @@ Texture* TextureList::zTexture(const char* name) const
 //  id: The id of the texture
 Texture* TextureList::zTexture(int id) const
 {
-    cs.lock();
+    lock.lockRead();
     for (auto i : *textures)
     {
         if (i->getId() == id)
         {
-            cs.unlock();
+            lock.unlockRead();
             return i;
         }
     }
-    cs.unlock();
+    lock.unlockRead();
     return 0;
-}
-
-// static functions
-
-// Initializes static private members. Called automatically by the framework.
-void TextureList::init()
-{
-    id = 0;
-}
-
-// Deletes static private members. Called automatically by the framework.
-void TextureList::destroy() {}
+}

+ 2 - 8
TextureList.h

@@ -12,8 +12,8 @@ namespace Framework
     class TextureList : public virtual ReferenceCounter
     {
     private:
-        static int id;
-        static Critical cs;
+        int nextId;
+        mutable ReadWriteLock lock;
         RCArray<Texture>* textures;
         RCArray<Text>* names;
 
@@ -46,11 +46,5 @@ namespace Framework
         //! Returns a specific texture without increased reference counter
         //! \param id The id of the texture
         DLLEXPORT Texture* zTexture(int id) const;
-        //! Initializes static private members. Called automatically by the
-        //! framework.
-        static void init();
-        //! Deletes static private members. Called automatically by the
-        //! framework.
-        static void destroy();
     };
 } // namespace Framework

+ 6 - 0
Thread.cpp

@@ -2,6 +2,10 @@
 
 #include "Globals.h"
 
+#ifndef WIN32
+#    include <unistd.h>
+#endif
+
 using namespace Framework;
 
 // Contents of the Thread class from Thread.h
@@ -165,6 +169,7 @@ void Thread::removeCriticalLock()
 #ifdef WIN32
 unsigned long __stdcall Framework::threadStart(void* param)
 {
+    currentThreadId = GetCurrentThreadId();
     if (isThreadOk((Thread*)param))
     {
         const char* name = ((Thread*)param)->getName();
@@ -181,6 +186,7 @@ unsigned long __stdcall Framework::threadStart(void* param)
 #else
 void* Framework::threadStart(void* param)
 {
+    currentThreadId = gettid();
     pthread_t handle = 0;
     pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, 0);
     if (isThreadOk((Thread*)param))

+ 2 - 1
Thread.h

@@ -97,7 +97,8 @@ namespace Framework
         //! \param t The thread to be removed
         void remove(Thread* t);
         //! Checks whether a pointer points to a valid Thread object, or
-        //! whether it has already been deleted \param t The pointer to be checked
+        //! whether it has already been deleted \param t The pointer to be
+        //! checked
         bool isThread(Thread* t);
         //! Searches for a specific thread and returns the corresponding object
         //! handle: A handle to the sought thread

+ 14 - 5
Window.cpp

@@ -281,12 +281,21 @@ LRESULT CALLBACK Framework::WindowProc(
 void Framework::StartMessageLoop()
 {
     MSG msg;
+    Timer tm;
     while (GetMessage(&msg, NULL, 0, 0) > 0 && !msgExit)
     {
         if (!msgExit)
         {
+            tm.measureStart();
             TranslateMessage(&msg);
             DispatchMessage(&msg);
+            tm.measureEnd();
+            if (tm.getSekunden() > 0.1)
+            {
+                Logging::warning()
+                    << "Message loop is taking too long: "
+                    << std::to_string(tm.getSekunden()) << " seconds";
+            }
         }
     }
     msgExit = 0;
@@ -1850,10 +1859,10 @@ void Window::render(Image& zRObj) // draws to zRObj
 {
     if (hasStyle(Style::Visible))
     {
-        lockDrawable();
+        rwLock.lockRead();
         if (!zRObj.setDrawOptions(pos, gr))
         {
-            unlockDrawable();
+            rwLock.unlockRead();
             return;
         }
         Drawable::render(zRObj);
@@ -1881,7 +1890,7 @@ void Window::render(Image& zRObj) // draws to zRObj
             if (!zRObj.setDrawOptions(rbr, rbr, gr.x - rbr * 2, th))
             {
                 zRObj.releaseDrawOptions();
-                unlockDrawable();
+                rwLock.unlockRead();
                 return;
             }
             int sbr = 0;
@@ -1961,7 +1970,7 @@ void Window::render(Image& zRObj) // draws to zRObj
         if (!zRObj.setDrawOptions(x, y, br, hi))
         {
             zRObj.releaseDrawOptions();
-            unlockDrawable();
+            rwLock.unlockRead();
             return;
         }
         if (hasStyle(Style::BodyBackground))
@@ -1997,7 +2006,7 @@ void Window::render(Image& zRObj) // draws to zRObj
         }
         zRObj.releaseDrawOptions();
         zRObj.releaseDrawOptions();
-        unlockDrawable();
+        rwLock.unlockRead();
     }
 }
 

+ 30 - 14
World3D.cpp

@@ -31,22 +31,22 @@ World3D::~World3D()
 }
 
 // Blocks access to the object and waits for access if necessary
-void World3D::lock()
+Lock& World3D::readLock()
 {
-    cs.lock();
+    return lock.getReadLock();
 }
 
 // Releases the object for other threads
-void World3D::unlock()
+Lock& World3D::writeLock()
 {
-    cs.unlock();
+    return lock.getWriteLock();
 }
 
 // Adds an object to the world
 //  obj: The object to be added
 void World3D::addDrawable(Model3D* obj)
 {
-    cs.lock();
+    lock.lockWrite();
     if (debugDX)
     {
         for (auto i : *members)
@@ -56,14 +56,14 @@ void World3D::addDrawable(Model3D* obj)
     }
     members->add(obj);
     rend = 1;
-    cs.unlock();
+    lock.unlockWrite();
 }
 
 // Removes an object from the world
 //  obj: The object to be removed
 void World3D::removeDrawable(Model3D* obj)
 {
-    cs.lock();
+    lock.lockWrite();
     int index = 0;
     for (Model3D* member : *members)
     {
@@ -75,24 +75,24 @@ void World3D::removeDrawable(Model3D* obj)
         }
         index++;
     }
-    cs.unlock();
+    lock.unlockWrite();
 }
 
 //! Adds a collection of objects to the world
 //! \param collection The collection to be added
 void World3D::addCollection(Model3DCollection* collection)
 {
-    cs.lock();
+    lock.lockWrite();
     modelCollections.add(collection);
     rend = 1;
-    cs.unlock();
+    lock.unlockWrite();
 }
 
 //! removes a collection of models from the world
 //! \param zCollection The collection to be removed
 void World3D::removeCollection(Model3DCollection* zCollection)
 {
-    cs.lock();
+    lock.lockWrite();
     int index = 0;
     for (Model3DCollection* collection : modelCollections)
     {
@@ -104,7 +104,7 @@ void World3D::removeCollection(Model3DCollection* zCollection)
         }
         index++;
     }
-    cs.unlock();
+    lock.unlockWrite();
 }
 
 // Processes a mouse event
@@ -168,10 +168,10 @@ void World3D::doMouseEvent(MouseEvent3D& me)
 //  otherwise.
 bool World3D::tick(double tickval)
 {
-    cs.lock();
+    lock.lockRead();
     rend |= tick(
         [this, &tickval](Model3D* m) { rend |= m->tick(tickval); }, tickval);
-    cs.unlock();
+    lock.unlockRead();
     bool tmp = rend;
     rend = 0;
     return tmp;
@@ -187,6 +187,7 @@ int World3D::traceRay(Vec3<float>& point, Vec3<float>& dir)
     float min = INFINITY;
     int pId = 0;
     Model3D* nearest = 0;
+    lock.lockRead();
     forAll([this, &point, &dir, &pId, &min, &nearest](Model3D* m) {
         float tmp = m->traceRay(point, dir, min, pId);
         if (min > tmp && tmp >= 0)
@@ -195,6 +196,7 @@ int World3D::traceRay(Vec3<float>& point, Vec3<float>& dir)
             nearest = m;
         }
     });
+    lock.unlockRead();
     if (nearest) return nearest->traceRay(point, dir, pId, this);
     return 0xFF000000;
 }
@@ -202,30 +204,36 @@ int World3D::traceRay(Vec3<float>& point, Vec3<float>& dir)
 //! executes a function on every model
 void Framework::World3D::forAll(std::function<void(Model3D*)> f)
 {
+    lock.lockRead();
     for (auto m : *members)
         f(m);
     for (auto c : modelCollections)
         c->forAll(f);
+    lock.unlockRead();
 }
 
 //! executes a tick function on every model
 bool World3D::tick(std::function<void(Model3D*)> f, double time)
 {
+    lock.lockRead();
     for (auto m : *members)
         f(m);
     bool res = 0;
     for (auto c : modelCollections)
         res |= c->tick(f, time);
+    lock.unlockRead();
     return res;
 }
 
 //! executes a render function on every model
 void World3D::render(std::function<void(Model3D*)> f)
 {
+    lock.lockRead();
     for (auto m : *members)
         f(m);
     for (auto c : modelCollections)
         c->render(f);
+    lock.unlockRead();
 }
 
 int Framework::World3D::getPointLightCount() const
@@ -252,6 +260,7 @@ void Framework::World3D::copyLight(DXBuffer* zDiffuse, DXBuffer* zPoints) const
 //! \param light The new light source
 void Framework::World3D::addDiffuseLight(DiffuseLight light)
 {
+    lock.lockWrite();
     DiffuseLight* tmp = new DiffuseLight[diffuseLightCount + 1];
     for (int i = 0; i < diffuseLightCount; i++)
     {
@@ -261,12 +270,14 @@ void Framework::World3D::addDiffuseLight(DiffuseLight light)
     delete[] diffuseLights;
     diffuseLights = tmp;
     diffuseLightCount++;
+    lock.unlockWrite();
 }
 
 //! adds a new point light source
 //! \param light The new light source
 void Framework::World3D::addPointLight(PointLight light)
 {
+    lock.lockWrite();
     PointLight* tmp = new PointLight[pointLightCount + 1];
     for (int i = 0; i < pointLightCount; i++)
     {
@@ -276,6 +287,7 @@ void Framework::World3D::addPointLight(PointLight light)
     delete[] pointLights;
     pointLights = tmp;
     pointLightCount++;
+    lock.unlockWrite();
 }
 
 //! Returns the reference to a diffuse light source
@@ -296,20 +308,24 @@ PointLight& Framework::World3D::getPointLight(int index) const
 //! \param index the index of the light
 DLLEXPORT void Framework::World3D::removeDiffuseLight(int index)
 {
+    lock.lockWrite();
     for (int i = index; i < diffuseLightCount - 1; i++)
     {
         diffuseLights[i] = diffuseLights[i + 1];
     }
     diffuseLightCount--;
+    lock.unlockWrite();
 }
 
 //! removes a specific point light from the world
 //! \param index the index of the light
 DLLEXPORT void Framework::World3D::removePointLight(int index)
 {
+    lock.lockWrite();
     for (int i = index; i < pointLightCount - 1; i++)
     {
         pointLights[i] = pointLights[i + 1];
     }
     pointLightCount--;
+    lock.unlockWrite();
 }

+ 9 - 8
World3D.h

@@ -8,8 +8,8 @@
 
 namespace Framework
 {
-    class Drawable3D;     //! Drawing.h
-    class Render3D;        //! Render3D.h
+    class Drawable3D;    //! Drawing.h
+    class Render3D;      //! Render3D.h
     struct MouseEvent3D; //! MouseEvent.h
     class Model3D;
     class DXBuffer;
@@ -28,22 +28,23 @@ namespace Framework
     private:
         RCArray<Model3D>* members;
         bool rend;
-        Critical cs;
+        ReadWriteLock lock;
 
     public:
         //! Constructor
         DLLEXPORT World3D();
         //! Destructor
         DLLEXPORT virtual ~World3D();
-        //! Locks access to the object and waits for access if necessary
-        DLLEXPORT void lock();
-        //! Releases the object for other threads
-        DLLEXPORT void unlock();
+        //! returns a lock for reading the object
+        DLLEXPORT Lock& readLock();
+        //! returns a lock for writing the object
+        DLLEXPORT Lock& writeLock();
         //! Adds an object to the world
         //! \param obj The object to add
         DLLEXPORT void addDrawable(Model3D* obj);
         //! Removes an object from the world
-        //! \param obj The object to remove (without increased reference counter)
+        //! \param obj The object to remove (without increased reference
+        //! counter)
         DLLEXPORT void removeDrawable(Model3D* zObj);
         //! Adds a collection of objects to the world
         //! \param collection The collection to add