Rename DocumentReader/Writer -> DocReader/Writer

This commit is contained in:
David Capello 2018-07-14 22:47:03 -03:00
parent e88952572c
commit 8d3da46ac9
17 changed files with 275 additions and 279 deletions

View File

@ -1,5 +1,5 @@
// Aseprite
// Copyright (C) 2001-2017 David Capello
// Copyright (C) 2001-2018 David Capello
//
// This program is distributed under the terms of
// the End-User License Agreement for Aseprite.
@ -12,7 +12,6 @@
#include "app/commands/command.h"
#include "app/commands/commands.h"
#include "app/context_access.h"
#include "app/document_access.h"
#include "app/modules/editors.h"
#include "app/ui/document_view.h"
#include "app/ui/status_bar.h"

View File

@ -54,7 +54,7 @@ public:
, m_index_bg_color(-1)
, m_doublebuf(Image::create(IMAGE_RGB, ui::display_w(), ui::display_h()))
, m_doublesur(she::instance()->createRgbaSurface(ui::display_w(), ui::display_h())) {
// Do not use DocumentWriter (do not lock the document) because we
// Do not use DocWriter (do not lock the document) because we
// will call other sub-commands (e.g. previous frame, next frame,
// etc.).
View* view = View::getView(editor);

View File

@ -14,7 +14,7 @@
#include "app/commands/params.h"
#include "app/context.h"
#include "app/context_access.h"
#include "app/document_access.h"
#include "app/doc_access.h"
#include "app/doc_api.h"
#include "app/i18n/strings.h"
#include "app/modules/editors.h"
@ -199,7 +199,7 @@ private:
releaseEditor();
if (m_fileOpened) {
DocumentDestroyer destroyer(m_context, oldDocument, 100);
DocDestroyer destroyer(m_context, oldDocument, 100);
destroyer.destroyDocument();
}
}

View File

@ -445,7 +445,7 @@ void SaveFileCopyAsCommand::moveToUndoState(Doc* doc,
const undo::UndoState* state)
{
try {
DocumentWriter writer(doc, 100);
DocWriter writer(doc, 100);
doc->undoHistory()->moveToState(state);
doc->generateMaskBoundaries();
doc->notifyGeneralUpdate();

View File

@ -17,7 +17,7 @@
#include "app/doc_undo.h"
#include "app/doc_undo_observer.h"
#include "app/docs_observer.h"
#include "app/document_access.h"
#include "app/doc_access.h"
#include "app/modules/gui.h"
#include "app/modules/palettes.h"
#include "app/site.h"
@ -98,7 +98,7 @@ private:
if (m_document &&
m_document->undoHistory()->currentState() != item->state()) {
try {
DocumentWriter writer(m_document, 100);
DocWriter writer(m_document, 100);
m_document->undoHistory()->moveToState(item->state());
m_document->generateMaskBoundaries();

View File

@ -8,7 +8,7 @@
#define APP_CONTEXT_ACCESS_H_INCLUDED
#pragma once
#include "app/document_access.h"
#include "app/doc_access.h"
#include "app/site.h"
namespace app {
@ -51,10 +51,10 @@ namespace app {
{
}
template<typename DocumentReaderT>
ContextAccess(const Context* context, const DocumentReaderT& documentReader, int timeout)
template<typename DocReaderT>
ContextAccess(const Context* context, const DocReaderT& docReader, int timeout)
: m_context(context)
, m_document(documentReader, timeout)
, m_document(docReader, timeout)
, m_site(context->activeSite())
{
}
@ -67,23 +67,23 @@ namespace app {
// You can use this class to access to the given context to read the
// active document.
class ContextReader : public ContextAccess<DocumentReader> {
class ContextReader : public ContextAccess<DocReader> {
public:
ContextReader(const Context* context, int timeout = 0)
: ContextAccess<DocumentReader>(context, timeout) {
: ContextAccess<DocReader>(context, timeout) {
}
};
// You can use this class to access to the given context to write the
// active document.
class ContextWriter : public ContextAccess<DocumentWriter> {
class ContextWriter : public ContextAccess<DocWriter> {
public:
ContextWriter(const Context* context, int timeout = 0)
: ContextAccess<DocumentWriter>(context, timeout) {
: ContextAccess<DocWriter>(context, timeout) {
}
ContextWriter(const ContextReader& reader, int timeout = 0)
: ContextAccess<DocumentWriter>(reader.context(), reader.document(), timeout) {
: ContextAccess<DocWriter>(reader.context(), reader.document(), timeout) {
}
};

View File

@ -21,7 +21,7 @@
#include "app/context.h"
#include "app/crash/session.h"
#include "app/doc.h"
#include "app/document_access.h"
#include "app/doc_access.h"
#include "app/document_diff.h"
#include "app/pref/preferences.h"
#include "base/bind.h"
@ -128,7 +128,7 @@ void BackupObserver::backgroundThread()
}
#ifdef TEST_BACKUP_INTEGRITY
else {
DocumentReader reader(doc, 500);
DocReader reader(doc, 500);
std::unique_ptr<Doc> copy(
m_session->restoreBackupDocById(doc->id()));
DocumentDiff diff = compare_docs(doc, copy.get());

View File

@ -15,7 +15,7 @@
#include "app/crash/read_document.h"
#include "app/crash/write_document.h"
#include "app/doc.h"
#include "app/document_access.h"
#include "app/doc_access.h"
#include "app/file/file.h"
#include "app/ui_context.h"
#include "base/bind.h"
@ -142,11 +142,11 @@ void Session::removeFromDisk()
}
}
class CustomWeakDocumentReader : public WeakDocumentReader
, public doc::CancelIO {
class CustomWeakDocReader : public WeakDocReader
, public doc::CancelIO {
public:
explicit CustomWeakDocumentReader(Doc* doc)
: WeakDocumentReader(doc) {
explicit CustomWeakDocReader(Doc* doc)
: WeakDocReader(doc) {
}
// CancelIO impl
@ -157,7 +157,7 @@ public:
bool Session::saveDocumentChanges(Doc* doc)
{
CustomWeakDocumentReader reader(doc);
CustomWeakDocReader reader(doc);
if (!reader.isLocked())
return false;

234
src/app/doc_access.h Normal file
View File

@ -0,0 +1,234 @@
// Aseprite
// Copyright (C) 2001-2018 David Capello
//
// This program is distributed under the terms of
// the End-User License Agreement for Aseprite.
#ifndef APP_DOC_ACCESS_H_INCLUDED
#define APP_DOC_ACCESS_H_INCLUDED
#pragma once
#include "app/context.h"
#include "app/doc.h"
#include "base/exception.h"
#include <exception>
namespace app {
// TODO remove exceptions and use "DocAccess::operator bool()"
class LockedDocException : public base::Exception {
public:
LockedDocException(const char* msg) throw()
: base::Exception(msg) { }
};
class CannotReadDocException : public LockedDocException {
public:
CannotReadDocException() throw()
: LockedDocException("Cannot read the sprite.\n"
"It is being modified by another command.\n"
"Try again.") { }
};
class CannotWriteDocException : public LockedDocException {
public:
CannotWriteDocException() throw()
: LockedDocException("Cannot modify the sprite.\n"
"It is being used by another command.\n"
"Try again.") { }
};
// This class acts like a wrapper for the given document. It's
// specialized by DocReader/Writer to handle document read/write
// locks.
class DocAccess {
public:
DocAccess() : m_doc(NULL) { }
DocAccess(const DocAccess& copy) : m_doc(copy.m_doc) { }
explicit DocAccess(Doc* doc) : m_doc(doc) { }
~DocAccess() { }
DocAccess& operator=(const DocAccess& copy) {
m_doc = copy.m_doc;
return *this;
}
operator Doc*() { return m_doc; }
operator const Doc*() const { return m_doc; }
Doc* operator->() {
ASSERT(m_doc);
return m_doc;
}
const Doc* operator->() const {
ASSERT(m_doc);
return m_doc;
}
protected:
Doc* m_doc;
};
// Class to view the document's state. Its constructor request a
// reader-lock of the document, or throws an exception in case that
// the lock cannot be obtained.
class DocReader : public DocAccess {
public:
DocReader() {
}
explicit DocReader(Doc* doc, int timeout)
: DocAccess(doc) {
if (m_doc && !m_doc->lock(Doc::ReadLock, timeout))
throw CannotReadDocException();
}
explicit DocReader(const DocReader& copy, int timeout)
: DocAccess(copy) {
if (m_doc && !m_doc->lock(Doc::ReadLock, timeout))
throw CannotReadDocException();
}
~DocReader() {
unlock();
}
protected:
void unlock() {
if (m_doc) {
m_doc->unlock();
m_doc = nullptr;
}
}
private:
// Disable operator=
DocReader& operator=(const DocReader&);
};
// Class to modify the document's state. Its constructor request a
// writer-lock of the document, or throws an exception in case that
// the lock cannot be obtained. Also, it contains a special
// constructor that receives a DocReader, to elevate the
// reader-lock to writer-lock.
class DocWriter : public DocAccess {
public:
DocWriter()
: m_from_reader(false)
, m_locked(false) {
}
explicit DocWriter(Doc* doc, int timeout)
: DocAccess(doc)
, m_from_reader(false)
, m_locked(false) {
if (m_doc) {
if (!m_doc->lock(Doc::WriteLock, timeout))
throw CannotWriteDocException();
m_locked = true;
}
}
// Constructor that can be used to elevate the given reader-lock to
// writer permission.
explicit DocWriter(const DocReader& doc, int timeout)
: DocAccess(doc)
, m_from_reader(true)
, m_locked(false) {
if (m_doc) {
if (!m_doc->upgradeToWrite(timeout))
throw CannotWriteDocException();
m_locked = true;
}
}
~DocWriter() {
unlock();
}
protected:
void unlock() {
if (m_doc && m_locked) {
if (m_from_reader)
m_doc->downgradeToRead();
else
m_doc->unlock();
m_doc = nullptr;
m_locked = false;
}
}
private:
bool m_from_reader;
bool m_locked;
// Non-copyable
DocWriter(const DocWriter&);
DocWriter& operator=(const DocWriter&);
DocWriter& operator=(const DocReader&);
};
// Used to destroy the active document in the context.
class DocDestroyer : public DocWriter {
public:
explicit DocDestroyer(Context* context, Doc* doc, int timeout)
: DocWriter(doc, timeout) {
}
void destroyDocument() {
ASSERT(m_doc != NULL);
m_doc->close();
Doc* doc = m_doc;
unlock();
delete doc;
m_doc = nullptr;
}
};
class WeakDocReader : public DocAccess {
public:
WeakDocReader() {
}
explicit WeakDocReader(Doc* doc)
: DocAccess(doc)
, m_weak_lock(base::RWLock::WeakUnlocked) {
if (m_doc)
m_doc->weakLock(&m_weak_lock);
}
~WeakDocReader() {
weakUnlock();
}
bool isLocked() const {
return (m_weak_lock == base::RWLock::WeakLocked);
}
protected:
void weakUnlock() {
if (m_doc && m_weak_lock != base::RWLock::WeakUnlocked) {
m_doc->weakUnlock();
m_doc = nullptr;
}
}
private:
// Disable operator=
WeakDocReader(const WeakDocReader&);
WeakDocReader& operator=(const WeakDocReader&);
base::RWLock::WeakLock m_weak_lock;
};
} // namespace app
#endif

View File

@ -1,237 +0,0 @@
// Aseprite
// Copyright (C) 2001-2018 David Capello
//
// This program is distributed under the terms of
// the End-User License Agreement for Aseprite.
#ifndef APP_DOCUMENT_ACCESS_H_INCLUDED
#define APP_DOCUMENT_ACCESS_H_INCLUDED
#pragma once
#include "app/context.h"
#include "app/doc.h"
#include "base/exception.h"
#include <exception>
namespace app {
// TODO remove exceptions and use "DocumentAccess::operator bool()"
class LockedDocumentException : public base::Exception {
public:
LockedDocumentException(const char* msg) throw()
: base::Exception(msg) { }
};
class CannotReadDocumentException : public LockedDocumentException {
public:
CannotReadDocumentException() throw()
: LockedDocumentException("Cannot read the sprite.\n"
"It is being modified by another command.\n"
"Try again.") { }
};
class CannotWriteDocumentException : public LockedDocumentException {
public:
CannotWriteDocumentException() throw()
: LockedDocumentException("Cannot modify the sprite.\n"
"It is being used by another command.\n"
"Try again.") { }
};
// This class acts like a wrapper for the given document. It's
// specialized by DocumentReader/Writer to handle document read/write
// locks.
class DocumentAccess {
public:
DocumentAccess() : m_document(NULL) { }
DocumentAccess(const DocumentAccess& copy) : m_document(copy.m_document) { }
explicit DocumentAccess(Doc* document) : m_document(document) { }
~DocumentAccess() { }
DocumentAccess& operator=(const DocumentAccess& copy)
{
m_document = copy.m_document;
return *this;
}
operator Doc* () { return m_document; }
operator const Doc* () const { return m_document; }
Doc* operator->()
{
ASSERT(m_document != NULL);
return m_document;
}
const Doc* operator->() const
{
ASSERT(m_document != NULL);
return m_document;
}
protected:
Doc* m_document;
};
// Class to view the document's state. Its constructor request a
// reader-lock of the document, or throws an exception in case that
// the lock cannot be obtained.
class DocumentReader : public DocumentAccess {
public:
DocumentReader() {
}
explicit DocumentReader(Doc* document, int timeout)
: DocumentAccess(document) {
if (m_document && !m_document->lock(Doc::ReadLock, timeout))
throw CannotReadDocumentException();
}
explicit DocumentReader(const DocumentReader& copy, int timeout)
: DocumentAccess(copy) {
if (m_document && !m_document->lock(Doc::ReadLock, timeout))
throw CannotReadDocumentException();
}
~DocumentReader() {
unlock();
}
protected:
void unlock() {
if (m_document) {
m_document->unlock();
m_document = nullptr;
}
}
private:
// Disable operator=
DocumentReader& operator=(const DocumentReader&);
};
// Class to modify the document's state. Its constructor request a
// writer-lock of the document, or throws an exception in case that
// the lock cannot be obtained. Also, it contains a special
// constructor that receives a DocumentReader, to elevate the
// reader-lock to writer-lock.
class DocumentWriter : public DocumentAccess {
public:
DocumentWriter()
: m_from_reader(false)
, m_locked(false) {
}
explicit DocumentWriter(Doc* document, int timeout)
: DocumentAccess(document)
, m_from_reader(false)
, m_locked(false) {
if (m_document) {
if (!m_document->lock(Doc::WriteLock, timeout))
throw CannotWriteDocumentException();
m_locked = true;
}
}
// Constructor that can be used to elevate the given reader-lock to
// writer permission.
explicit DocumentWriter(const DocumentReader& document, int timeout)
: DocumentAccess(document)
, m_from_reader(true)
, m_locked(false) {
if (m_document) {
if (!m_document->upgradeToWrite(timeout))
throw CannotWriteDocumentException();
m_locked = true;
}
}
~DocumentWriter() {
unlock();
}
protected:
void unlock() {
if (m_document && m_locked) {
if (m_from_reader)
m_document->downgradeToRead();
else
m_document->unlock();
m_document = nullptr;
m_locked = false;
}
}
private:
bool m_from_reader;
bool m_locked;
// Non-copyable
DocumentWriter(const DocumentWriter&);
DocumentWriter& operator=(const DocumentWriter&);
DocumentWriter& operator=(const DocumentReader&);
};
// Used to destroy the active document in the context.
class DocumentDestroyer : public DocumentWriter {
public:
explicit DocumentDestroyer(Context* context, Doc* document, int timeout)
: DocumentWriter(document, timeout) {
}
void destroyDocument() {
ASSERT(m_document != NULL);
m_document->close();
Doc* doc = m_document;
unlock();
delete doc;
m_document = nullptr;
}
};
class WeakDocumentReader : public DocumentAccess {
public:
WeakDocumentReader() {
}
explicit WeakDocumentReader(Doc* doc)
: DocumentAccess(doc)
, m_weak_lock(base::RWLock::WeakUnlocked) {
if (m_document)
m_document->weakLock(&m_weak_lock);
}
~WeakDocumentReader() {
weakUnlock();
}
bool isLocked() const {
return (m_weak_lock == base::RWLock::WeakLocked);
}
protected:
void weakUnlock() {
if (m_document && m_weak_lock != base::RWLock::WeakUnlocked) {
m_document->weakUnlock();
m_document = nullptr;
}
}
private:
// Disable operator=
WeakDocumentReader(const WeakDocumentReader&);
WeakDocumentReader& operator=(const WeakDocumentReader&);
base::RWLock::WeakLock m_weak_lock;
};
} // namespace app
#endif

View File

@ -19,7 +19,7 @@
#include "app/console.h"
#include "app/context_access.h"
#include "app/doc_event.h"
#include "app/document_access.h"
#include "app/doc_access.h"
#include "app/i18n/strings.h"
#include "app/modules/editors.h"
#include "app/modules/palettes.h"
@ -320,7 +320,7 @@ bool DocumentView::onCloseView(Workspace* workspace, bool quitting)
try {
// Destroy the sprite (locking it as writer)
DocumentDestroyer destroyer(
DocDestroyer destroyer(
static_cast<app::Context*>(m_document->context()), m_document, 500);
StatusBar::instance()
@ -332,7 +332,7 @@ bool DocumentView::onCloseView(Workspace* workspace, bool quitting)
// At this point the view is already destroyed
return true;
}
catch (const LockedDocumentException& ex) {
catch (const LockedDocException& ex) {
Console::showException(ex);
return false;
}

View File

@ -1825,7 +1825,7 @@ void Editor::onPaint(ui::PaintEvent& ev)
try {
// Lock the sprite to read/render it. We wait 1/4 secs in case
// the background thread is making a backup.
DocumentReader documentReader(m_document, 250);
DocReader documentReader(m_document, 250);
// Draw the sprite in the editor
renderChrono.reset();
@ -1862,7 +1862,7 @@ void Editor::onPaint(ui::PaintEvent& ev)
m_antsTimer.stop();
}
}
catch (const LockedDocumentException&) {
catch (const LockedDocException&) {
// The sprite is locked to be read, so we can draw an opaque
// background only.
g->fillRect(theme->colors.editorFace(), rc);

View File

@ -133,7 +133,7 @@ void MovingPixelsState::rotate(double angle)
{
m_pixelsMovement->rotate(angle);
}
void MovingPixelsState::flip(doc::algorithm::FlipType flipType)
{
m_pixelsMovement->flipImage(flipType);
@ -164,7 +164,7 @@ EditorState::LeaveAction MovingPixelsState::onLeaveState(Editor* editor, EditorS
try {
m_pixelsMovement->dropImage();
}
catch (const LockedDocumentException& ex) {
catch (const LockedDocException& ex) {
// This is one of the worst possible scenarios. We want to
// drop pixels because we're leaving this state (e.g. the user
// changed the current frame/layer, so we came from
@ -646,7 +646,7 @@ void MovingPixelsState::setTransparentColor(bool opaque, const app::Color& color
m_pixelsMovement->setMaskColor(
opaque, color_utils::color_for_target_mask(color, ColorTarget(layer)));
}
catch (const LockedDocumentException& ex) {
catch (const LockedDocException& ex) {
Console::showException(ex);
}
}

View File

@ -195,7 +195,7 @@ bool StandbyState::onMouseDown(Editor* editor, MouseMessage* msg)
editor, msg, handle, collect);
editor->setState(EditorStatePtr(newState));
}
catch (const LockedDocumentException&) {
catch (const LockedDocException&) {
// TODO break the background task that is locking this sprite
StatusBar::instance()->showTip(
1000, "Sprite is used by a backup/data recovery task");
@ -676,11 +676,11 @@ void StandbyState::startSelectionTransformation(Editor* editor,
void StandbyState::startFlipTransformation(Editor* editor, doc::algorithm::FlipType flipType)
{
transformSelection(editor, NULL, NoHandle);
if (MovingPixelsState* movingPixels = dynamic_cast<MovingPixelsState*>(editor->getState().get()))
movingPixels->flip(flipType);
}
void StandbyState::transformSelection(Editor* editor, MouseMessage* msg, HandleType handle)
{
Doc* document = editor->document();
@ -730,7 +730,7 @@ void StandbyState::transformSelection(Editor* editor, MouseMessage* msg, HandleT
editor->setState(EditorStatePtr(new MovingPixelsState(editor, msg, pixelsMovement, handle)));
}
catch (const LockedDocumentException&) {
catch (const LockedDocException&) {
// Other editor is locking the document.
// TODO steal the PixelsMovement of the other editor and use it for this one.

View File

@ -456,7 +456,7 @@ public:
ContextWriter writer(reader, 500);
m_expandCelCanvas->commit();
}
catch (const LockedDocumentException& ex) {
catch (const LockedDocException& ex) {
Console::showException(ex);
}
}
@ -487,7 +487,7 @@ public:
ContextWriter writer(reader, 500);
m_expandCelCanvas->rollback();
}
catch (const LockedDocumentException& ex) {
catch (const LockedDocException& ex) {
Console::showException(ex);
}
}

View File

@ -12,8 +12,8 @@
#include "app/commands/commands.h"
#include "app/commands/params.h"
#include "app/context_access.h"
#include "app/doc_access.h"
#include "app/doc_event.h"
#include "app/document_access.h"
#include "app/doc_range.h"
#include "app/modules/editors.h"
#include "app/modules/gfx.h"

View File

@ -1480,7 +1480,7 @@ void Timeline::onPaint(ui::PaintEvent& ev)
try {
// Lock the sprite to read/render it. We wait 1/4 secs in case
// the background thread is making a backup.
const DocumentReader documentReader(m_document, 250);
const DocReader docReader(m_document, 250);
if (m_redrawMarchingAntsOnly) {
drawClipboardRange(g);
@ -1615,7 +1615,7 @@ void Timeline::onPaint(ui::PaintEvent& ev)
}
#endif
}
catch (const LockedDocumentException&) {
catch (const LockedDocException&) {
noDoc = true;
defer_invalid_rect(g->getClipBounds().offset(bounds().origin()));
}