From efa4847a61bb484cd544db95027f54ab60bf2fb3 Mon Sep 17 00:00:00 2001 From: Joel Holdsworth Date: Sat, 13 Dec 2008 16:56:02 +0000 Subject: [PATCH 001/214] Added to_list method for read only STL list access to the observable_list --- src/common/observable-list.hpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/common/observable-list.hpp b/src/common/observable-list.hpp index ed7fec8d6..c672d2a1b 100644 --- a/src/common/observable-list.hpp +++ b/src/common/observable-list.hpp @@ -263,6 +263,19 @@ public: changed.emit(); } +public: + /* ===== Conversions ===== */ + + /** + * Returns a copy of this observable_list converted to an STL list + * object. + * @return Returns a copy of the STL list. + **/ + std::list to_list() const + { + return list; + } + public: /* ===== Signals ===== */ From 6cbd4282c1dd92858455935bf8a3b2c485b70412 Mon Sep 17 00:00:00 2001 From: Joel Holdsworth Date: Sat, 13 Dec 2008 16:58:41 +0000 Subject: [PATCH 002/214] Restructured model track tree, and improved child access --- src/gui/Makefile.am | 8 ++--- src/gui/model/group-track.cpp | 6 ---- src/gui/model/group-track.hpp | 12 ++----- .../{track-base.cpp => parent-track.cpp} | 24 +++++++------ .../{track-base.hpp => parent-track.hpp} | 35 +++++++++++-------- src/gui/model/sequence.cpp | 6 ---- src/gui/model/sequence.hpp | 9 ++--- src/gui/model/track.cpp | 8 +++++ src/gui/model/track.hpp | 11 ++++-- .../timeline/timeline-header-container.cpp | 2 +- .../timeline/timeline-header-container.hpp | 2 +- 11 files changed, 62 insertions(+), 61 deletions(-) rename src/gui/model/{track-base.cpp => parent-track.cpp} (71%) rename src/gui/model/{track-base.hpp => parent-track.hpp} (68%) diff --git a/src/gui/Makefile.am b/src/gui/Makefile.am index 1c4c0fb67..ef0031754 100644 --- a/src/gui/Makefile.am +++ b/src/gui/Makefile.am @@ -80,14 +80,14 @@ lumigui_SOURCES = \ $(lumigui_srcdir)/widgets/timeline/timeline-clip.hpp \ $(lumigui_srcdir)/model/project.cpp \ $(lumigui_srcdir)/model/project.hpp \ - $(lumigui_srcdir)/model/track-base.cpp \ - $(lumigui_srcdir)/model/track-base.hpp \ - $(lumigui_srcdir)/model/sequence.cpp \ - $(lumigui_srcdir)/model/sequence.hpp \ $(lumigui_srcdir)/model/track.cpp \ $(lumigui_srcdir)/model/track.hpp \ $(lumigui_srcdir)/model/clip-track.cpp \ $(lumigui_srcdir)/model/clip-track.hpp \ + $(lumigui_srcdir)/model/parent-track.cpp \ + $(lumigui_srcdir)/model/parent-track.hpp \ + $(lumigui_srcdir)/model/sequence.cpp \ + $(lumigui_srcdir)/model/sequence.hpp \ $(lumigui_srcdir)/model/group-track.cpp \ $(lumigui_srcdir)/model/group-track.hpp \ $(lumigui_srcdir)/model/clip.cpp \ diff --git a/src/gui/model/group-track.cpp b/src/gui/model/group-track.cpp index a71d8db6c..c7572b4d9 100644 --- a/src/gui/model/group-track.cpp +++ b/src/gui/model/group-track.cpp @@ -28,12 +28,6 @@ namespace model { GroupTrack::GroupTrack() { } - -const std::list< boost::shared_ptr >& -GroupTrack::get_child_tracks() const -{ - return children; -} } // namespace model } // namespace gui diff --git a/src/gui/model/group-track.hpp b/src/gui/model/group-track.hpp index eb047cf37..de5ac8f4b 100644 --- a/src/gui/model/group-track.hpp +++ b/src/gui/model/group-track.hpp @@ -26,22 +26,16 @@ #ifndef GROUP_TRACK_HPP #define GROUP_TRACK_HPP -#include "track.hpp" +#include "parent-track.hpp" namespace gui { namespace model { -class GroupTrack : public Track +class GroupTrack : public ParentTrack { public: GroupTrack(); - - const std::list< boost::shared_ptr >& - get_child_tracks() const; - -private: - //----- Data -----// - std::list< boost::shared_ptr > children; + }; } // namespace model diff --git a/src/gui/model/track-base.cpp b/src/gui/model/parent-track.cpp similarity index 71% rename from src/gui/model/track-base.cpp rename to src/gui/model/parent-track.cpp index d6fd2357f..fa835e49a 100644 --- a/src/gui/model/track-base.cpp +++ b/src/gui/model/parent-track.cpp @@ -1,5 +1,5 @@ /* - track-base.cpp - Implementation of the TrackBase class + parent-track-.cpp - Implementation of the ParentTrack class Copyright (C) Lumiera.org 2008, Joel Holdsworth @@ -20,31 +20,35 @@ * *****************************************************/ -#include "track.hpp" +#include "parent-track.hpp" namespace gui { namespace model { -const std::list< boost::shared_ptr > TrackBase::NoChildren; - -TrackBase::TrackBase() +ParentTrack::ParentTrack() { } -const std::list< boost::shared_ptr >& -TrackBase::get_child_tracks() const +std::list< boost::shared_ptr > +ParentTrack::get_child_tracks() const { - return NoChildren; + return tracks.to_list(); +} + +lumiera::observable_list< boost::shared_ptr >& +ParentTrack::get_child_track_list() +{ + return tracks; } const Glib::ustring -TrackBase::get_name() const +ParentTrack::get_name() const { return name; } void -TrackBase::set_name(const Glib::ustring &name) +ParentTrack::set_name(const Glib::ustring &name) { this->name = name; } diff --git a/src/gui/model/track-base.hpp b/src/gui/model/parent-track.hpp similarity index 68% rename from src/gui/model/track-base.hpp rename to src/gui/model/parent-track.hpp index 5ae555e01..518140d9f 100644 --- a/src/gui/model/track-base.hpp +++ b/src/gui/model/parent-track.hpp @@ -1,5 +1,5 @@ /* - track-track.hpp - Definition of the TrackBase class + parent-track.hpp - Definition of the ParentTrack class Copyright (C) Lumiera.org 2008, Joel Holdsworth @@ -19,43 +19,48 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/** @file track-base.hpp - ** This file contains the definition of TrackBase, a class which +/** @file parent-track.hpp + ** This file contains the definition of ParentTrack, a class which ** represents a base functionality for tracks and sequences which ** are also track parents. This class wraps proc layer data */ -#include "../gtk-lumiera.hpp" +#include "track.hpp" +#include "../../common/observable-list.hpp" -#ifndef TRACK_BASE_HPP -#define TRACK_BASE_HPP +#ifndef PARENT_TRACK_HPP +#define PARENT_TRACK_HPP namespace gui { namespace model { -class Track; - -class TrackBase +class ParentTrack : public Track { +protected: + ParentTrack(); + public: - TrackBase(); - virtual void add_child_track(Track* child) {}; - - virtual const std::list< boost::shared_ptr >& + + std::list< boost::shared_ptr > get_child_tracks() const; + + lumiera::observable_list< boost::shared_ptr >& + get_child_track_list(); const Glib::ustring get_name() const; void set_name(const Glib::ustring &name); private: + //----- Data -----// Glib::ustring name; - static const std::list< boost::shared_ptr > NoChildren; +protected: + lumiera::observable_list< boost::shared_ptr > tracks; }; } // namespace model } // namespace gui -#endif // TRACK_BASE_HPP +#endif // PARENT_TRACK_HPP diff --git a/src/gui/model/sequence.cpp b/src/gui/model/sequence.cpp index e480b02db..87d9d1dc7 100644 --- a/src/gui/model/sequence.cpp +++ b/src/gui/model/sequence.cpp @@ -49,11 +49,5 @@ Sequence::Sequence() // END TEST CODE } -const std::list< boost::shared_ptr >& -Sequence::get_child_tracks() const -{ - return tracks; -} - } // namespace model } // namespace gui diff --git a/src/gui/model/sequence.hpp b/src/gui/model/sequence.hpp index 2df7a3f11..02a2869c2 100644 --- a/src/gui/model/sequence.hpp +++ b/src/gui/model/sequence.hpp @@ -27,7 +27,7 @@ #ifndef SEQUENCE_HPP #define SEQUENCE_HPP -#include "track-base.hpp" +#include "parent-track.hpp" // TEST CODE #include "group-track.hpp" @@ -38,17 +38,14 @@ namespace model { class Track; -class Sequence : public TrackBase +class Sequence : public ParentTrack { public: Sequence(); - const std::list< boost::shared_ptr >& - get_child_tracks() const; private: - //----- Data -----// - std::list< boost::shared_ptr > tracks; + }; } // namespace model diff --git a/src/gui/model/track.cpp b/src/gui/model/track.cpp index 8541e17f9..03c8f88e5 100644 --- a/src/gui/model/track.cpp +++ b/src/gui/model/track.cpp @@ -24,11 +24,19 @@ namespace gui { namespace model { + +const std::list< boost::shared_ptr > Track::NoChildren; Track::Track() { } +std::list< boost::shared_ptr > +Track::get_child_tracks() const +{ + return Track::NoChildren; +} + } // namespace model } // namespace gui diff --git a/src/gui/model/track.hpp b/src/gui/model/track.hpp index 4fe852b30..60357f56e 100644 --- a/src/gui/model/track.hpp +++ b/src/gui/model/track.hpp @@ -24,7 +24,7 @@ ** represents a track, and wraps proc layer data */ -#include "track-base.hpp" +#include "../gtk-lumiera.hpp" #ifndef TRACK_HPP #define TRACK_HPP @@ -32,12 +32,17 @@ namespace gui { namespace model { -class Track : public TrackBase +class Track { -public: +protected: Track(); +public: + virtual std::list< boost::shared_ptr > + get_child_tracks() const; +protected: + static const std::list< boost::shared_ptr > NoChildren; }; } // namespace model diff --git a/src/gui/widgets/timeline/timeline-header-container.cpp b/src/gui/widgets/timeline/timeline-header-container.cpp index c9330d109..d0dac87c5 100644 --- a/src/gui/widgets/timeline/timeline-header-container.cpp +++ b/src/gui/widgets/timeline/timeline-header-container.cpp @@ -497,7 +497,7 @@ TimelineHeaderContainer::lookup_timeline_track( return timeline_track; } -const std::list< boost::shared_ptr >& +const std::list< boost::shared_ptr > TimelineHeaderContainer::get_tracks() const { REQUIRE(timelineWidget != NULL); diff --git a/src/gui/widgets/timeline/timeline-header-container.hpp b/src/gui/widgets/timeline/timeline-header-container.hpp index 082f1e871..f787c5547 100644 --- a/src/gui/widgets/timeline/timeline-header-container.hpp +++ b/src/gui/widgets/timeline/timeline-header-container.hpp @@ -215,7 +215,7 @@ private: * @return Returns the track found, or returns NULL if no matching * track was found. **/ - const std::list< boost::shared_ptr >& + const std::list< boost::shared_ptr > get_tracks() const; /** From f3ea24260dcc08bdc31dc5d1c2d4513555c4d53e Mon Sep 17 00:00:00 2001 From: Joel Holdsworth Date: Tue, 16 Dec 2008 20:31:04 +0000 Subject: [PATCH 003/214] Added a stub menu item for add track --- src/gui/workspace/actions.cpp | 13 +++++++++++++ src/gui/workspace/actions.hpp | 2 ++ src/gui/workspace/workspace-window.cpp | 3 +++ 3 files changed, 18 insertions(+) diff --git a/src/gui/workspace/actions.cpp b/src/gui/workspace/actions.cpp index f18c44ccb..6afe2c2a8 100644 --- a/src/gui/workspace/actions.cpp +++ b/src/gui/workspace/actions.cpp @@ -92,6 +92,11 @@ Actions::Actions(WorkspaceWindow &workspace_window) : actionGroup->add(Action::create("SequenceMenu", _("_Sequence"))); actionGroup->add(Action::create("SequenceAdd", _("_Add...")), sigc::mem_fun(*this, &Actions::on_menu_sequence_add)); + + // Track Menu + actionGroup->add(Action::create("TrackMenu", _("_Track"))); + actionGroup->add(Action::create("TrackAdd", _("_Add...")), + sigc::mem_fun(*this, &Actions::on_menu_track_add)); // Help Menu actionGroup->add(Action::create("HelpMenu", _("_Help")) ); @@ -186,6 +191,14 @@ Actions::on_menu_sequence_add() workspaceWindow.get_project()->add_new_sequence(dialog.get_name()); } +/* ===== Track Menu Event Handlers ===== */ + +void +Actions::on_menu_track_add() +{ + g_message("Hello"); +} + /* ===== View Menu Event Handlers ===== */ void diff --git a/src/gui/workspace/actions.hpp b/src/gui/workspace/actions.hpp index b3662591e..76034ac6e 100644 --- a/src/gui/workspace/actions.hpp +++ b/src/gui/workspace/actions.hpp @@ -71,6 +71,8 @@ private: void on_menu_view_viewer(); void on_menu_sequence_add(); + + void on_menu_track_add(); void on_menu_help_about(); diff --git a/src/gui/workspace/workspace-window.cpp b/src/gui/workspace/workspace-window.cpp index 96f33e4e8..5b9e49bd9 100644 --- a/src/gui/workspace/workspace-window.cpp +++ b/src/gui/workspace/workspace-window.cpp @@ -116,6 +116,9 @@ WorkspaceWindow::create_ui() " " " " " " + " " + " " + " " " " " " " " From 081b630a9c6ebb1a45af2b75ccc848f7ebe0e527 Mon Sep 17 00:00:00 2001 From: Joel Holdsworth Date: Tue, 16 Dec 2008 20:56:47 +0000 Subject: [PATCH 004/214] Fixed some problems introduced during merging --- src/backend/Makefile.am | 2 +- src/gui/Makefile.am | 88 ++++------------------------------------- 2 files changed, 9 insertions(+), 81 deletions(-) diff --git a/src/backend/Makefile.am b/src/backend/Makefile.am index 62e744b47..6fa1391e5 100644 --- a/src/backend/Makefile.am +++ b/src/backend/Makefile.am @@ -19,7 +19,7 @@ liblumibackend_a_srcdir = $(top_srcdir)/src/backend noinst_LIBRARIES += liblumibackend.a liblumibackend_a_CPPFLAGS = $(AM_CPPFLAGS) -liblumibackend_a_CFLAGS = $(AM_CFLAGS) -std=gnu99 -Wextra -Wall -Werror +liblumibackend_a_CFLAGS = $(AM_CFLAGS) -std=gnu99 -Wextra -Wall liblumibackend_a_SOURCES = \ $(liblumibackend_a_srcdir)/mediaaccessfacade.cpp \ diff --git a/src/gui/Makefile.am b/src/gui/Makefile.am index 3e712ce8a..6bac5c0e0 100644 --- a/src/gui/Makefile.am +++ b/src/gui/Makefile.am @@ -20,15 +20,14 @@ lumigui_srcdir = $(top_srcdir)/src/gui #lumigui_CFLAGS = $(CFLAGS) -std=gnu99 -Wall -Werror -lumigui_CPPFLAGS = $(AM_CPPFLAGS) \ - -DPACKAGE_LOCALE_DIR=\""$(prefix)/$(DATADIRNAME)/locale"\" \ - -DPACKAGE_SRC_DIR=\""$(srcdir)"\" \ - -DPACKAGE_DATA_DIR=\""$(datadir)"\" \ +lumigui_CPPFLAGS = $(AM_CPPFLAGS) \ + -DPACKAGE_LOCALE_DIR=\""$(prefix)/$(DATADIRNAME)/locale"\" \ + -DPACKAGE_SRC_DIR=\""$(srcdir)"\" \ + -DPACKAGE_DATA_DIR=\""$(datadir)"\" \ $(LUMIERA_GUI_CFLAGS) bin_PROGRAMS += lumigui -<<<<<<< HEAD:src/gui/Makefile.am lumigui_SOURCES = \ $(lumigui_srcdir)/gtk-lumiera.cpp \ $(lumigui_srcdir)/gtk-lumiera.hpp \ @@ -83,14 +82,14 @@ lumigui_SOURCES = \ $(lumigui_srcdir)/model/project.hpp \ $(lumigui_srcdir)/model/track.cpp \ $(lumigui_srcdir)/model/track.hpp \ - $(lumigui_srcdir)/model/clip-track.cpp \ - $(lumigui_srcdir)/model/clip-track.hpp \ $(lumigui_srcdir)/model/parent-track.cpp \ $(lumigui_srcdir)/model/parent-track.hpp \ - $(lumigui_srcdir)/model/sequence.cpp \ - $(lumigui_srcdir)/model/sequence.hpp \ $(lumigui_srcdir)/model/group-track.cpp \ $(lumigui_srcdir)/model/group-track.hpp \ + $(lumigui_srcdir)/model/sequence.cpp \ + $(lumigui_srcdir)/model/sequence.hpp \ + $(lumigui_srcdir)/model/clip-track.cpp \ + $(lumigui_srcdir)/model/clip-track.hpp \ $(lumigui_srcdir)/model/clip.cpp \ $(lumigui_srcdir)/model/clip.hpp \ $(lumigui_srcdir)/output/displayer.cpp \ @@ -98,77 +97,6 @@ lumigui_SOURCES = \ $(lumigui_srcdir)/output/gdkdisplayer.cpp \ $(lumigui_srcdir)/output/gdkdisplayer.hpp \ $(lumigui_srcdir)/output/xvdisplayer.cpp \ -======= -lumigui_SOURCES = \ - $(lumigui_srcdir)/gtk-lumiera.cpp \ - $(lumigui_srcdir)/gtk-lumiera.hpp \ - $(lumigui_srcdir)/window-manager.cpp \ - $(lumigui_srcdir)/window-manager.hpp \ - $(lumigui_srcdir)/workspace/actions.cpp \ - $(lumigui_srcdir)/workspace/actions.hpp \ - $(lumigui_srcdir)/workspace/workspace-window.cpp \ - $(lumigui_srcdir)/workspace/workspace-window.hpp \ - $(lumigui_srcdir)/dialogs/dialog.hpp \ - $(lumigui_srcdir)/dialogs/render.cpp \ - $(lumigui_srcdir)/dialogs/render.hpp \ - $(lumigui_srcdir)/dialogs/preferences-dialog.cpp \ - $(lumigui_srcdir)/dialogs/preferences-dialog.hpp \ - $(lumigui_srcdir)/dialogs/sequence-name.cpp \ - $(lumigui_srcdir)/dialogs/sequence-name.hpp \ - $(lumigui_srcdir)/panels/panel.cpp \ - $(lumigui_srcdir)/panels/panel.hpp \ - $(lumigui_srcdir)/panels/timeline-panel.cpp \ - $(lumigui_srcdir)/panels/timeline-panel.hpp \ - $(lumigui_srcdir)/panels/viewer-panel.cpp \ - $(lumigui_srcdir)/panels/viewer-panel.hpp \ - $(lumigui_srcdir)/panels/assets-panel.cpp \ - $(lumigui_srcdir)/panels/assets-panel.hpp \ - $(lumigui_srcdir)/widgets/video-display-widget.cpp \ - $(lumigui_srcdir)/widgets/video-display-widget.hpp \ - $(lumigui_srcdir)/widgets/timeline-widget.cpp \ - $(lumigui_srcdir)/widgets/timeline-widget.hpp \ - $(lumigui_srcdir)/widgets/timeline/timeline-view-window.cpp \ - $(lumigui_srcdir)/widgets/timeline/timeline-view-window.hpp \ - $(lumigui_srcdir)/widgets/timeline/timeline-header-container.cpp \ - $(lumigui_srcdir)/widgets/timeline/timeline-header-container.hpp \ - $(lumigui_srcdir)/widgets/timeline/timeline-body.cpp \ - $(lumigui_srcdir)/widgets/timeline/timeline-body.hpp \ - $(lumigui_srcdir)/widgets/timeline/timeline-ruler.cpp \ - $(lumigui_srcdir)/widgets/timeline/timeline-ruler.hpp \ - $(lumigui_srcdir)/widgets/timeline/timeline-tool.cpp \ - $(lumigui_srcdir)/widgets/timeline/timeline-tool.hpp \ - $(lumigui_srcdir)/widgets/timeline/timeline-arrow-tool.cpp \ - $(lumigui_srcdir)/widgets/timeline/timeline-arrow-tool.hpp \ - $(lumigui_srcdir)/widgets/timeline/timeline-ibeam-tool.cpp \ - $(lumigui_srcdir)/widgets/timeline/timeline-ibeam-tool.hpp \ - $(lumigui_srcdir)/widgets/timeline/timeline-track.cpp \ - $(lumigui_srcdir)/widgets/timeline/timeline-track.hpp \ - $(lumigui_srcdir)/widgets/timeline/timeline-clip-track.cpp \ - $(lumigui_srcdir)/widgets/timeline/timeline-clip-track.hpp \ - $(lumigui_srcdir)/widgets/timeline/timeline-group-track.cpp \ - $(lumigui_srcdir)/widgets/timeline/timeline-group-track.hpp \ - $(lumigui_srcdir)/widgets/timeline/timeline-clip.cpp \ - $(lumigui_srcdir)/widgets/timeline/timeline-clip.hpp \ - $(lumigui_srcdir)/model/project.cpp \ - $(lumigui_srcdir)/model/project.hpp \ - $(lumigui_srcdir)/model/track-base.cpp \ - $(lumigui_srcdir)/model/track-base.hpp \ - $(lumigui_srcdir)/model/sequence.cpp \ - $(lumigui_srcdir)/model/sequence.hpp \ - $(lumigui_srcdir)/model/track.cpp \ - $(lumigui_srcdir)/model/track.hpp \ - $(lumigui_srcdir)/model/clip-track.cpp \ - $(lumigui_srcdir)/model/clip-track.hpp \ - $(lumigui_srcdir)/model/group-track.cpp \ - $(lumigui_srcdir)/model/group-track.hpp \ - $(lumigui_srcdir)/model/clip.cpp \ - $(lumigui_srcdir)/model/clip.hpp \ - $(lumigui_srcdir)/output/displayer.cpp \ - $(lumigui_srcdir)/output/displayer.hpp \ - $(lumigui_srcdir)/output/gdkdisplayer.cpp \ - $(lumigui_srcdir)/output/gdkdisplayer.hpp \ - $(lumigui_srcdir)/output/xvdisplayer.cpp \ ->>>>>>> 9a1a1890e27942a7f45a3593f525c55cb5e8d8cb:src/gui/Makefile.am $(lumigui_srcdir)/output/xvdisplayer.hpp lumigui_LDFLAGS = From d9b747a5447968e05d1214e9a7769a648603f339 Mon Sep 17 00:00:00 2001 From: Joel Holdsworth Date: Tue, 16 Dec 2008 21:29:35 +0000 Subject: [PATCH 005/214] Revert "try to make icon-render-script more robust regarding the output destination" This reverts commit bd538edfe9f8d17ce01adae98391cab9dbd46229. Conflicts: admin/render-icon.py --- admin/render-icon.py | 31 ++++++++++++------------------- 1 file changed, 12 insertions(+), 19 deletions(-) diff --git a/admin/render-icon.py b/admin/render-icon.py index 4b0d464ca..bf9715bc9 100755 --- a/admin/render-icon.py +++ b/admin/render-icon.py @@ -1,5 +1,5 @@ #!/usr/bin/python -# + # render-icons.py - Icon rendering utility script # # Copyright (C) Lumiera.org @@ -20,10 +20,9 @@ # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. import sys -import os -import os.path as Path import getopt from xml.dom import minidom +import os import shutil #svgDir = "svg" @@ -33,20 +32,14 @@ rsvgPath = "./rsvg-convert" artworkLayerPrefix = "artwork:" def createDirectory( name ): - if Path.isfile(name): - print "WARNING: moving %s to %s.bak because it's in the way." % (name,name) - bak_name = name + ".bak" - if Path.isfile(bak_name): - os.remove(bak_name) - os.rename(name,bak_name) - if not Path.isdir(name): + if os.path.exists(name) == False: os.mkdir(name) def copyMergeDirectory( src, dst ): listing = os.listdir(src) for file_name in listing: - src_file_path = Path.join(src, file_name) - dst_file_path = Path.join(dst, file_name) + src_file_path = os.path.join(src, file_name) + dst_file_path = os.path.join(dst, file_name) shutil.copyfile(src_file_path, dst_file_path) def getDocumentSize( svg_element ): @@ -165,19 +158,19 @@ def main(argv): print "Missing arguments in_path and out_dir." sys.exit(1) - if Path.isfile(out_dir): + if os.path.isfile(out_dir): print "Unable to use '%s' as output directory, because it\'s a file." % out_dir sys.exit(1) - if not Path.isdir(out_dir): + if not os.path.isdir(out_dir): print "Output directory '%s' not found." % out_dir sys.exit(1) # Create the icons folders - createDirectory(Path.join(out_dir, "48x48")) - createDirectory(Path.join(out_dir, "32x32")) - createDirectory(Path.join(out_dir, "24x24")) - createDirectory(Path.join(out_dir, "22x22")) - createDirectory(Path.join(out_dir, "16x16")) + createDirectory(os.path.join(out_dir, "48x48")) + createDirectory(os.path.join(out_dir, "32x32")) + createDirectory(os.path.join(out_dir, "24x24")) + createDirectory(os.path.join(out_dir, "22x22")) + createDirectory(os.path.join(out_dir, "16x16")) renderSvgIcon(in_path, out_dir) From dd255ce3d5e6c1f965a972a6d35486c77841e3a0 Mon Sep 17 00:00:00 2001 From: Joel Holdsworth Date: Tue, 16 Dec 2008 22:19:44 +0000 Subject: [PATCH 006/214] Added 22x22 and 24x24 images to track icons --- icons/svg/track-disabled.svg | 571 ++-------------------- icons/svg/track-enabled.svg | 863 ++++----------------------------- icons/svg/track-locked.svg | 899 ++++++++--------------------------- icons/svg/track-unlocked.svg | 843 +++++++++++++++----------------- 4 files changed, 708 insertions(+), 2468 deletions(-) diff --git a/icons/svg/track-disabled.svg b/icons/svg/track-disabled.svg index 04e87768e..1527b8352 100644 --- a/icons/svg/track-disabled.svg +++ b/icons/svg/track-disabled.svg @@ -41,544 +41,20 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + inkscape:window-y="24"> + + @@ -644,13 +130,12 @@ sodipodi:nodetypes="czcsc" id="path13699" d="M 139.5,84.9691 C 137.3345,87.776 134.73,88.4358 132.1148,88.4358 C 129.4995,88.4358 126.2207,87.9797 125.7142,84.9691 C 126.2637,82.2163 127.6839,80.5318 131.3314,80.5005 C 135.3174,80.4664 137.2533,83.0122 139.5,84.9691 z" - style="opacity:0.9;fill:url(#radialGradient15234);fill-opacity:1;fill-rule:evenodd;stroke:#888a85;stroke-width:1;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0.70164642;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" /> + style="display:inline;opacity:0.90000000000000002;fill:url(#radialGradient15234);fill-opacity:1;fill-rule:evenodd;stroke:#888a85;stroke-width:1;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0.70164641999999999;stroke-opacity:1;visibility:visible;overflow:visible;enable-background:accumulate" /> diff --git a/icons/svg/track-enabled.svg b/icons/svg/track-enabled.svg index ab6af9f53..277b3d17c 100644 --- a/icons/svg/track-enabled.svg +++ b/icons/svg/track-enabled.svg @@ -31,15 +31,6 @@ offset="1" id="stop14234" /> - - @@ -78,747 +58,6 @@ offset="1" id="stop13606" /> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + inkscape:window-y="24"> + + + + + + + + diff --git a/icons/svg/track-locked.svg b/icons/svg/track-locked.svg index 3ff1d34a4..990c034b7 100644 --- a/icons/svg/track-locked.svg +++ b/icons/svg/track-locked.svg @@ -30,26 +30,6 @@ offset="1.0000000" id="stop9849" /> - - - @@ -91,16 +61,6 @@ offset="1" id="stop12075" /> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + gradientTransform="matrix(0.2913951,0,0,0.3423373,103.01101,72.677438)" + x1="10.907269" + y1="25.002281" + x2="30.875446" + y2="36.127281" /> + + + + + + + + inkscape:window-y="24"> - - - - - - - + + + + + + + + + + + + + + + + + diff --git a/icons/svg/track-unlocked.svg b/icons/svg/track-unlocked.svg index beea19846..40866bf5f 100644 --- a/icons/svg/track-unlocked.svg +++ b/icons/svg/track-unlocked.svg @@ -19,6 +19,56 @@ inkscape:output_extension="org.inkscape.output.svg.inkscape"> + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + inkscape:window-y="24"> - - - - - - + style="display:inline"> + + + + + + + + + + + + + + + + + + + + + + From 0e8252188faef4dc500f8dc35a3b478689f45abd Mon Sep 17 00:00:00 2001 From: Joel Holdsworth Date: Tue, 16 Dec 2008 22:24:06 +0000 Subject: [PATCH 007/214] Tweaked 48x48 arrow tool icon to render more crisply --- icons/svg/tool-arrow.svg | 508 +++++---------------------------------- 1 file changed, 66 insertions(+), 442 deletions(-) diff --git a/icons/svg/tool-arrow.svg b/icons/svg/tool-arrow.svg index 3f0b72102..84807f4fb 100644 --- a/icons/svg/tool-arrow.svg +++ b/icons/svg/tool-arrow.svg @@ -54,44 +54,6 @@ offset="1" id="stop8777" /> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + inkscape:window-x="1280" + inkscape:window-y="24"> + + + + + + + + + + + + + - - - - - - - - - From 21ba2de6ed66aa7e793dca913811820e49802265 Mon Sep 17 00:00:00 2001 From: Joel Holdsworth Date: Tue, 16 Dec 2008 22:25:00 +0000 Subject: [PATCH 008/214] Did a vacuum defs on tool-i-beam.svg --- icons/svg/tool-i-beam.svg | 485 +------------------------------------- 1 file changed, 3 insertions(+), 482 deletions(-) diff --git a/icons/svg/tool-i-beam.svg b/icons/svg/tool-i-beam.svg index da244f5bb..337a75027 100644 --- a/icons/svg/tool-i-beam.svg +++ b/icons/svg/tool-i-beam.svg @@ -19,29 +19,6 @@ inkscape:output_extension="org.inkscape.output.svg.inkscape"> - - - - - - - - @@ -54,44 +31,6 @@ offset="1" id="stop8777" /> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + inkscape:window-x="1280" + inkscape:window-y="24"> Date: Tue, 16 Dec 2008 22:55:32 +0000 Subject: [PATCH 009/214] Fixed set_icon_size for temporary Debian Etch compatibility --- configure.ac | 7 ++++++- src/gui/widgets/timeline/timeline-track.cpp | 15 +++++++++++++-- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/configure.ac b/configure.ac index 09f68cc21..eb78e6d9a 100644 --- a/configure.ac +++ b/configure.ac @@ -135,8 +135,13 @@ PKG_CHECK_MODULES(LUMIERA_COMMON_LIBS, [sigc++-2.0 >= 2.0.18]) # END Internatinalization ############## Gtk Dependancies + +# gtk+-2.0 >= 2.8 gtkmm-2.4 >= 2.8 for Debian Etch compatibility +# gtk+-2.0 >= 2.12 gtkmm-2.4 >= 2.12 for Debian Lenny compatibility + PKG_CHECK_MODULES(LUMIERA_GUI, [ - gtkmm-2.4 >= 2.8 gdl-1.0 >= 0.6.1 cairomm-1.0 >= 0.6.0 + gtk+-2.0 >= 2.8 gtkmm-2.4 >= 2.8 + gdl-1.0 >= 0.6.1 cairomm-1.0 >= 0.6.0 gavl >= 0.2.5 librsvg-2.0 >= 2.18.1]) # END Gtk Dependancies diff --git a/src/gui/widgets/timeline/timeline-track.cpp b/src/gui/widgets/timeline/timeline-track.cpp index 8dc698969..a81af1858 100644 --- a/src/gui/widgets/timeline/timeline-track.cpp +++ b/src/gui/widgets/timeline/timeline-track.cpp @@ -20,6 +20,9 @@ * *****************************************************/ +#warning This header must soon be removed when we drop Etch compatibility +#include + #include "timeline-track.hpp" #include "../../window-manager.hpp" @@ -38,8 +41,16 @@ Track::Track() : buttonBar.append(lockButton); buttonBar.set_toolbar_style(TOOLBAR_ICONS); -//buttonBar.set_icon_size(WindowManager::MenuIconSize); -//TODO uncommented for now, doesn't compile on etch. 12/15/08 ichthyo + +#if 0 + buttonBar.set_icon_size(WindowManager::MenuIconSize); +#else +#warning This code soon be removed when we drop Etch compatibility + + // Temporary bodge for etch compatibility - will be removed soon + gtk_toolbar_set_icon_size (buttonBar.gobj(), + (GtkIconSize)(int)WindowManager::MenuIconSize); +#endif headerWidget.pack_start(titleBox, PACK_SHRINK); headerWidget.pack_start(buttonBar, PACK_SHRINK); From 35cfe48dfc34b22d2691967a0617137f973e7a6d Mon Sep 17 00:00:00 2001 From: Joel Holdsworth Date: Wed, 17 Dec 2008 00:03:30 +0000 Subject: [PATCH 010/214] Added a context menu with an "Add Track" command --- src/gui/widgets/timeline-widget.cpp | 25 +++++++++++++++ src/gui/widgets/timeline-widget.hpp | 8 +++++ .../timeline/timeline-header-container.cpp | 32 +++++++++++++++---- .../timeline/timeline-header-container.hpp | 2 ++ 4 files changed, 61 insertions(+), 6 deletions(-) diff --git a/src/gui/widgets/timeline-widget.cpp b/src/gui/widgets/timeline-widget.cpp index ec62d9e5f..3b9ebc7b5 100644 --- a/src/gui/widgets/timeline-widget.cpp +++ b/src/gui/widgets/timeline-widget.cpp @@ -85,6 +85,10 @@ TimelineWidget::TimelineWidget( attach(verticalScroll, 2, 3, 1, 2, SHRINK, FILL|EXPAND); set_tool(timeline::Arrow); + + // Receive notifications of changes to the tracks + sequence->get_child_track_list().signal_changed().connect( + sigc::mem_fun( this, &TimelineWidget::on_track_list_changed ) ); } TimelineWidget::~TimelineWidget() @@ -268,6 +272,16 @@ TimelineWidget::on_view_window_changed() viewWindow.get_time_offset()); } +void +TimelineWidget::on_add_track_command() +{ + REQUIRE(sequence); + + // # TEST CODE + sequence->get_child_track_list().push_back( + shared_ptr(new model::ClipTrack())); +} + /* ===== Internals ===== */ void @@ -296,10 +310,15 @@ void TimelineWidget::create_timeline_tracks() { REQUIRE(sequence); + REQUIRE(headerContainer != NULL); + REQUIRE(body != NULL); BOOST_FOREACH(shared_ptr child, sequence->get_child_tracks()) create_timeline_tracks_from_branch(child); + + headerContainer->show_all_children(); + body->queue_draw(); } void @@ -442,6 +461,12 @@ TimelineWidget::on_motion_in_body_notify_event(GdkEventMotion *event) return true; } +void +TimelineWidget::on_track_list_changed() +{ + update_tracks(); +} + void TimelineWidget::on_playback_period_drag_released() { diff --git a/src/gui/widgets/timeline-widget.hpp b/src/gui/widgets/timeline-widget.hpp index f4b1d38d6..065f8ea74 100644 --- a/src/gui/widgets/timeline-widget.hpp +++ b/src/gui/widgets/timeline-widget.hpp @@ -154,6 +154,8 @@ protected: void on_view_window_changed(); + void on_add_track_command(); + /* ===== Utilities ===== */ protected: @@ -214,6 +216,12 @@ private: int get_y_scroll_offset() const; // ----- Event Handlers -----// + + /** + * An event handler that receives notifications for when the + * sequence's track tree has been changed. + **/ + void on_track_list_changed(); void on_playback_period_drag_released(); diff --git a/src/gui/widgets/timeline/timeline-header-container.cpp b/src/gui/widgets/timeline/timeline-header-container.cpp index d0dac87c5..c70b1379f 100644 --- a/src/gui/widgets/timeline/timeline-header-container.cpp +++ b/src/gui/widgets/timeline/timeline-header-container.cpp @@ -81,6 +81,12 @@ TimelineHeaderContainer::on_realize() // Call base class: Gtk::Container::on_realize(); + // Create the context menu + Menu::MenuList& menu_list = contextMenu.items(); + menu_list.push_back( Menu_Helpers::MenuElem("_Add Track", + sigc::mem_fun(timelineWidget, + &TimelineWidget::on_add_track_command) ) ); + // Create the GdkWindow: GdkWindowAttr attributes; memset(&attributes, 0, sizeof(attributes)); @@ -129,15 +135,29 @@ TimelineHeaderContainer::on_unrealize() bool TimelineHeaderContainer::on_button_press_event ( GdkEventButton* event) { - // Did the user press the button on an expander? - if(hoveringExpander != NULL) + REQUIRE(event != NULL); + + switch(event->button) { - // Yes? The prime for a release event - clickedExpander = hoveringExpander; - queue_draw(); + case 1: // Left Click + // Did the user press the button on an expander? + if(hoveringExpander != NULL) + { + // Yes? The prime for a release event + clickedExpander = hoveringExpander; + queue_draw(); + } + break; + + case 3: // Right Click + // Popup the context menu + contextMenu.popup(event->button, event->time); + break; + + } - return Container::on_button_press_event(event); + return true; } bool TimelineHeaderContainer::on_button_release_event ( diff --git a/src/gui/widgets/timeline/timeline-header-container.hpp b/src/gui/widgets/timeline/timeline-header-container.hpp index f787c5547..612d70aca 100644 --- a/src/gui/widgets/timeline/timeline-header-container.hpp +++ b/src/gui/widgets/timeline/timeline-header-container.hpp @@ -246,6 +246,8 @@ private: std::map, Gdk::Rectangle> headerBoxes; + Gtk::Menu contextMenu; + //----- User Interaction State -----// boost::shared_ptr hoveringExpander; From 3914de5866b3b02055dc5b0dc287f4286c3d3dfb Mon Sep 17 00:00:00 2001 From: Joel Holdsworth Date: Wed, 17 Dec 2008 18:18:37 +0000 Subject: [PATCH 011/214] Silenced a GTK parenting warning --- src/gui/widgets/timeline/timeline-header-container.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/gui/widgets/timeline/timeline-header-container.cpp b/src/gui/widgets/timeline/timeline-header-container.cpp index c70b1379f..060199859 100644 --- a/src/gui/widgets/timeline/timeline-header-container.cpp +++ b/src/gui/widgets/timeline/timeline-header-container.cpp @@ -371,8 +371,14 @@ void TimelineHeaderContainer::set_parent_recursive( boost::shared_ptr model_track) { - lookup_timeline_track(model_track)-> - get_header_widget().set_parent(*this); + Widget &widget = lookup_timeline_track(model_track)-> + get_header_widget(); + + const Container *parent = widget.get_parent(); + if(parent == NULL) // Is the header unparented? + widget.set_parent(*this); + else if(parent != this) // The header is parented by another container + widget.reparent(*this); // Recurse through all the children BOOST_FOREACH( boost::shared_ptr child, From 0c55dfb85f40daef270f263996bf31278a089bff Mon Sep 17 00:00:00 2001 From: Joel Holdsworth Date: Wed, 17 Dec 2008 18:20:52 +0000 Subject: [PATCH 012/214] Tidied set_parent_recursive --- src/gui/widgets/timeline/timeline-header-container.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/gui/widgets/timeline/timeline-header-container.cpp b/src/gui/widgets/timeline/timeline-header-container.cpp index 060199859..4c3566c24 100644 --- a/src/gui/widgets/timeline/timeline-header-container.cpp +++ b/src/gui/widgets/timeline/timeline-header-container.cpp @@ -371,6 +371,7 @@ void TimelineHeaderContainer::set_parent_recursive( boost::shared_ptr model_track) { + // Set the header's parent widget Widget &widget = lookup_timeline_track(model_track)-> get_header_widget(); @@ -381,7 +382,7 @@ TimelineHeaderContainer::set_parent_recursive( widget.reparent(*this); // Recurse through all the children - BOOST_FOREACH( boost::shared_ptr child, + BOOST_FOREACH( shared_ptr child, model_track->get_child_tracks() ) set_parent_recursive(child); } From 396b2b889f8d6c4e5fb8dda2aeeafa84d1257f10 Mon Sep 17 00:00:00 2001 From: Joel Holdsworth Date: Wed, 17 Dec 2008 18:32:28 +0000 Subject: [PATCH 013/214] Tidied and added some documentation to timeline-header-container.hpp --- .../timeline/timeline-header-container.hpp | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/gui/widgets/timeline/timeline-header-container.hpp b/src/gui/widgets/timeline/timeline-header-container.hpp index 612d70aca..749c43157 100644 --- a/src/gui/widgets/timeline/timeline-header-container.hpp +++ b/src/gui/widgets/timeline/timeline-header-container.hpp @@ -243,11 +243,23 @@ private: */ Glib::RefPtr gdkWindow; + /** + * The Menu object which will be displayed as the context menu when + * the user right clicks on the header container. + * @remarks The context menu will be displayed when the user's right + * click is not processed by track headers. + **/ + Gtk::Menu contextMenu; + + /** + * A map of tracks to the rectangles of their headers. + * @remarks This map is used as a cache, so that the rectangles don't + * need to be perpetually recalculated. This cache is regenerated by + * the layout_headers method. + **/ std::map, Gdk::Rectangle> headerBoxes; - Gtk::Menu contextMenu; - //----- User Interaction State -----// boost::shared_ptr hoveringExpander; From 8e551acb60abaa703990be017ff556de8339ee0c Mon Sep 17 00:00:00 2001 From: Joel Holdsworth Date: Wed, 17 Dec 2008 18:47:07 +0000 Subject: [PATCH 014/214] Added more documentation to timeline-header-container.hpp --- .../timeline/timeline-header-container.hpp | 28 +++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/src/gui/widgets/timeline/timeline-header-container.hpp b/src/gui/widgets/timeline/timeline-header-container.hpp index 749c43157..a45a71497 100644 --- a/src/gui/widgets/timeline/timeline-header-container.hpp +++ b/src/gui/widgets/timeline/timeline-header-container.hpp @@ -166,12 +166,19 @@ private: model_track); /** - * Recursively causes all the visible track header widgets to call - * size_request( ). + * Recursively causes all the visible track header widgets in a branch + * to call size_request( ). **/ void size_request_recursive( boost::shared_ptr model_track); + /** + * Recursively calls a callback on all the header widgets in a branch. + * @param model_track The root track of the branch. + * @param callback The callback to apply to the branch. This includes + * model_track and all it's children. + * @param callback_data The user data parameter for the callback. + **/ void forall_vfunc_recursive( boost::shared_ptr model_track, GtkCallback callback, gpointer callback_data); @@ -188,9 +195,22 @@ private: boost::shared_ptr model_track, const Gdk::Rectangle &clip_rect); + /** + * Given a point, expander_button_from_point finds the track of the + * expand button that this point is hovering over, if there is one. + * @param point The window coordiates point to hit-test. + * @return Returns a pointer to the track whose expander button is + * being hovered over, or NULL if no button has been found. + **/ boost::shared_ptr expander_button_from_point( const Gdk::Point &point); + /** + * Gets the rectangular hit-target area of a track header's expander + * button. + * @param track The track to get the expander button rectangle of. + * @return Returns the rectangle of the expander button of track. + **/ const Gdk::Rectangle get_expander_button_rectangle( boost::shared_ptr track); @@ -273,6 +293,10 @@ private: **/ int margin; + /** + * The style value which indicates the size to draw the expand button + * in pixels. + **/ int expand_button_size; }; From f3351d1380bac6e085d18516ac20723b1a7b61ed Mon Sep 17 00:00:00 2001 From: Joel Holdsworth Date: Wed, 17 Dec 2008 18:48:04 +0000 Subject: [PATCH 015/214] Removed a redundant include --- src/gui/widgets/timeline/timeline-header-container.hpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/gui/widgets/timeline/timeline-header-container.hpp b/src/gui/widgets/timeline/timeline-header-container.hpp index a45a71497..2ac07ad36 100644 --- a/src/gui/widgets/timeline/timeline-header-container.hpp +++ b/src/gui/widgets/timeline/timeline-header-container.hpp @@ -29,7 +29,6 @@ #define HEADER_CONTAINER_HPP #include "../../gtk-lumiera.hpp" -#include namespace gui { From cf6e174d85483459f8902a258a8107026571d704 Mon Sep 17 00:00:00 2001 From: Joel Holdsworth Date: Wed, 17 Dec 2008 18:55:38 +0000 Subject: [PATCH 016/214] Tidied TimelineHeaderContainer declaration, and relocated context menu setup there --- .../timeline/timeline-header-container.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/gui/widgets/timeline/timeline-header-container.cpp b/src/gui/widgets/timeline/timeline-header-container.cpp index 4c3566c24..11695afb5 100644 --- a/src/gui/widgets/timeline/timeline-header-container.cpp +++ b/src/gui/widgets/timeline/timeline-header-container.cpp @@ -36,8 +36,8 @@ namespace gui { namespace widgets { namespace timeline { -TimelineHeaderContainer::TimelineHeaderContainer(gui::widgets::TimelineWidget - *timeline_widget) : +TimelineHeaderContainer::TimelineHeaderContainer( + gui::widgets::TimelineWidget *timeline_widget) : Glib::ObjectBase("TimelineHeaderContainer"), timelineWidget(timeline_widget), margin(-1), @@ -61,6 +61,12 @@ TimelineHeaderContainer::TimelineHeaderContainer(gui::widgets::TimelineWidget sigc::mem_fun(this, &TimelineHeaderContainer::on_hovering_track_changed) ); + // Create the context menu + Menu::MenuList& menu_list = contextMenu.items(); + menu_list.push_back( Menu_Helpers::MenuElem("_Add Track", + sigc::mem_fun(timelineWidget, + &TimelineWidget::on_add_track_command) ) ); + // Install style properties register_styles(); } @@ -81,12 +87,6 @@ TimelineHeaderContainer::on_realize() // Call base class: Gtk::Container::on_realize(); - // Create the context menu - Menu::MenuList& menu_list = contextMenu.items(); - menu_list.push_back( Menu_Helpers::MenuElem("_Add Track", - sigc::mem_fun(timelineWidget, - &TimelineWidget::on_add_track_command) ) ); - // Create the GdkWindow: GdkWindowAttr attributes; memset(&attributes, 0, sizeof(attributes)); From 6cb533f564dfb11509c0501c4644153e1d14dd8a Mon Sep 17 00:00:00 2001 From: Joel Holdsworth Date: Sat, 20 Dec 2008 11:07:20 +0000 Subject: [PATCH 017/214] Corrected some source-formatting mistakes --- src/gui/widgets/timeline/timeline-track.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/gui/widgets/timeline/timeline-track.cpp b/src/gui/widgets/timeline/timeline-track.cpp index a81af1858..6cf2ae95f 100644 --- a/src/gui/widgets/timeline/timeline-track.cpp +++ b/src/gui/widgets/timeline/timeline-track.cpp @@ -68,12 +68,14 @@ Track::get_height() const return 100; } -bool Track::get_expanded() const +bool +Track::get_expanded() const { return expanded; } -void Track::set_expanded(bool expanded) +void +Track::set_expanded(bool expanded) { this->expanded = expanded; } From 715f76bc8d1340d0c75a93e82ff64f4daeee2d34 Mon Sep 17 00:00:00 2001 From: Joel Holdsworth Date: Sat, 20 Dec 2008 11:27:48 +0000 Subject: [PATCH 018/214] Made the header's context menu localizable --- src/gui/widgets/timeline/timeline-header-container.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/widgets/timeline/timeline-header-container.cpp b/src/gui/widgets/timeline/timeline-header-container.cpp index 11695afb5..e2cd0fe75 100644 --- a/src/gui/widgets/timeline/timeline-header-container.cpp +++ b/src/gui/widgets/timeline/timeline-header-container.cpp @@ -63,7 +63,7 @@ TimelineHeaderContainer::TimelineHeaderContainer( // Create the context menu Menu::MenuList& menu_list = contextMenu.items(); - menu_list.push_back( Menu_Helpers::MenuElem("_Add Track", + menu_list.push_back( Menu_Helpers::MenuElem(_("_Add Track"), sigc::mem_fun(timelineWidget, &TimelineWidget::on_add_track_command) ) ); From aafa600422c8f02eb2bc794b172b48cb1f597ebb Mon Sep 17 00:00:00 2001 From: Joel Holdsworth Date: Sat, 20 Dec 2008 11:45:23 +0000 Subject: [PATCH 019/214] Modified trackMap to map shared_ptr not model::Track* --- src/gui/widgets/timeline-widget.cpp | 9 ++++----- src/gui/widgets/timeline-widget.hpp | 3 ++- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/gui/widgets/timeline-widget.cpp b/src/gui/widgets/timeline-widget.cpp index 3b9ebc7b5..1300f10d4 100644 --- a/src/gui/widgets/timeline-widget.cpp +++ b/src/gui/widgets/timeline-widget.cpp @@ -328,12 +328,11 @@ TimelineWidget::create_timeline_tracks_from_branch( REQUIRE(model_track); // Is a timeline UI track present in the map already? - const model::Track *track = model_track.get(); - if(!contains(trackMap, track)) + if(!contains(trackMap, model_track)) { // The timeline UI track is not present // We will need to create one - trackMap[model_track.get()] = + trackMap[model_track] = create_timeline_track_from_model_track(model_track); } @@ -365,8 +364,8 @@ TimelineWidget::lookup_timeline_track( shared_ptr model_track) { REQUIRE(sequence); - std::map >:: - const_iterator iterator = trackMap.find(model_track.get()); + std::map, shared_ptr >:: + const_iterator iterator = trackMap.find(model_track); if(iterator == trackMap.end()) { // The track is not present in the map diff --git a/src/gui/widgets/timeline-widget.hpp b/src/gui/widgets/timeline-widget.hpp index 065f8ea74..062a61a6e 100644 --- a/src/gui/widgets/timeline-widget.hpp +++ b/src/gui/widgets/timeline-widget.hpp @@ -251,7 +251,8 @@ protected: * widget is updated with update_tracks, timeline tracks are added and * removed from the map in correspondance with the tree. **/ - std::map > + std::map, + boost::shared_ptr > trackMap; // View State From 3dd30c848d1778873a0223dbf6c969e7ced9a978 Mon Sep 17 00:00:00 2001 From: Joel Holdsworth Date: Sat, 20 Dec 2008 11:51:54 +0000 Subject: [PATCH 020/214] Added a const --- src/gui/widgets/timeline-widget.cpp | 2 +- src/gui/widgets/timeline-widget.hpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/gui/widgets/timeline-widget.cpp b/src/gui/widgets/timeline-widget.cpp index 1300f10d4..cce5682c5 100644 --- a/src/gui/widgets/timeline-widget.cpp +++ b/src/gui/widgets/timeline-widget.cpp @@ -361,7 +361,7 @@ TimelineWidget::create_timeline_track_from_model_track( shared_ptr TimelineWidget::lookup_timeline_track( - shared_ptr model_track) + shared_ptr model_track) const { REQUIRE(sequence); std::map, shared_ptr >:: diff --git a/src/gui/widgets/timeline-widget.hpp b/src/gui/widgets/timeline-widget.hpp index 062a61a6e..0e379eb11 100644 --- a/src/gui/widgets/timeline-widget.hpp +++ b/src/gui/widgets/timeline-widget.hpp @@ -204,7 +204,7 @@ private: * error condition). **/ boost::shared_ptr lookup_timeline_track( - boost::shared_ptr model_track); + boost::shared_ptr model_track) const; // ----- Layout Functions ----- // From bc2fdc40e937453207ffcefe41358d607122fd0a Mon Sep 17 00:00:00 2001 From: Joel Holdsworth Date: Sat, 20 Dec 2008 13:00:48 +0000 Subject: [PATCH 021/214] Transitioned TimelineHeaderContainer::headerBoxes from using shared_ptr to weak_ptr --- src/gui/gtk-lumiera.hpp | 1 + src/gui/widgets/timeline/timeline-header-container.cpp | 6 ++++-- src/gui/widgets/timeline/timeline-header-container.hpp | 2 +- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/gui/gtk-lumiera.hpp b/src/gui/gtk-lumiera.hpp index 6e0013a2c..ac2bfcc52 100644 --- a/src/gui/gtk-lumiera.hpp +++ b/src/gui/gtk-lumiera.hpp @@ -33,6 +33,7 @@ #include #include #include +#include #include "../common/util.hpp" extern "C" { diff --git a/src/gui/widgets/timeline/timeline-header-container.cpp b/src/gui/widgets/timeline/timeline-header-container.cpp index e2cd0fe75..e5b58d486 100644 --- a/src/gui/widgets/timeline/timeline-header-container.cpp +++ b/src/gui/widgets/timeline/timeline-header-container.cpp @@ -434,7 +434,8 @@ TimelineHeaderContainer::draw_header_decoration( lookup_timeline_track(model_track); // Get the cached header box - ASSERT(contains(headerBoxes, timeline_track)); + weak_ptr ptr(timeline_track); + ASSERT(contains(headerBoxes, ptr)); const Gdk::Rectangle &box = headerBoxes[timeline_track]; // Paint the box, if it will be visible @@ -502,7 +503,8 @@ TimelineHeaderContainer::get_expander_button_rectangle( shared_ptr track) { REQUIRE(track != NULL); - ASSERT(contains(headerBoxes, track)); + weak_ptr ptr(track); + ASSERT(contains(headerBoxes, ptr)); const Gdk::Rectangle &box = headerBoxes[track]; return Gdk::Rectangle( diff --git a/src/gui/widgets/timeline/timeline-header-container.hpp b/src/gui/widgets/timeline/timeline-header-container.hpp index 2ac07ad36..a035e104a 100644 --- a/src/gui/widgets/timeline/timeline-header-container.hpp +++ b/src/gui/widgets/timeline/timeline-header-container.hpp @@ -276,7 +276,7 @@ private: * need to be perpetually recalculated. This cache is regenerated by * the layout_headers method. **/ - std::map, Gdk::Rectangle> + std::map, Gdk::Rectangle> headerBoxes; //----- User Interaction State -----// From 992cd4d77bfe99fa2814a8ddabad5751d38fda62 Mon Sep 17 00:00:00 2001 From: Joel Holdsworth Date: Sat, 20 Dec 2008 14:31:11 +0000 Subject: [PATCH 022/214] Added remove track feature --- src/gui/widgets/timeline-widget.cpp | 84 +++++++++++++++++-- src/gui/widgets/timeline-widget.hpp | 25 +++++- .../widgets/timeline/timeline-clip-track.cpp | 3 +- .../widgets/timeline/timeline-clip-track.hpp | 2 +- .../widgets/timeline/timeline-group-track.cpp | 3 +- .../widgets/timeline/timeline-group-track.hpp | 2 +- .../timeline/timeline-header-container.cpp | 49 +++++++++-- .../timeline/timeline-header-container.hpp | 11 +++ src/gui/widgets/timeline/timeline-track.cpp | 30 ++++++- src/gui/widgets/timeline/timeline-track.hpp | 12 ++- 10 files changed, 204 insertions(+), 17 deletions(-) diff --git a/src/gui/widgets/timeline-widget.cpp b/src/gui/widgets/timeline-widget.cpp index cce5682c5..7798fba76 100644 --- a/src/gui/widgets/timeline-widget.cpp +++ b/src/gui/widgets/timeline-widget.cpp @@ -289,13 +289,20 @@ TimelineWidget::update_tracks() { REQUIRE(sequence); + // Remove any tracks which are no longer present in the model + remove_orphaned_tracks(); + // Create timeline tracks from all the model tracks create_timeline_tracks(); // Update the header container ASSERT(headerContainer != NULL); + headerContainer->show_all_children(); headerContainer->update_headers(); + // Update the body + body->queue_draw(); + // Recalculate the total height of the timeline scrolled area totalHeight = 0; BOOST_FOREACH(shared_ptr track, @@ -316,9 +323,6 @@ TimelineWidget::create_timeline_tracks() BOOST_FOREACH(shared_ptr child, sequence->get_child_tracks()) create_timeline_tracks_from_branch(child); - - headerContainer->show_all_children(); - body->queue_draw(); } void @@ -351,14 +355,59 @@ TimelineWidget::create_timeline_track_from_model_track( // Choose a corresponding timeline track class from the model track's // class if(typeid(*model_track) == typeid(model::ClipTrack)) - return shared_ptr(new timeline::ClipTrack()); + return shared_ptr(new timeline::ClipTrack(*this)); else if(typeid(*model_track) == typeid(model::GroupTrack)) - return shared_ptr(new timeline::GroupTrack()); + return shared_ptr(new timeline::GroupTrack(*this)); ASSERT(NULL); // Unknown track type; return shared_ptr(); } +void +TimelineWidget::remove_orphaned_tracks() +{ + REQUIRE(sequence); + REQUIRE(headerContainer != NULL); + REQUIRE(body != NULL); + + std::map, + boost::shared_ptr > + orphan_track_map(trackMap); + + // Remove all tracks which are still present in the sequence + BOOST_FOREACH(shared_ptr child, + sequence->get_child_tracks()) + search_orphaned_tracks_in_branch(child, orphan_track_map); + + // orphan_track_map now contains all the orphaned tracks + // Remove them + std::pair, shared_ptr > + pair; + BOOST_FOREACH( pair, orphan_track_map ) + { + ENSURE(pair.first) + trackMap.erase(pair.first); + } +} + +void +TimelineWidget::search_orphaned_tracks_in_branch( + boost::shared_ptr model_track, + std::map, + boost::shared_ptr > &orphan_track_map) +{ + REQUIRE(model_track); + + // Is the timeline UI still present? + if(contains(orphan_track_map, model_track)) + orphan_track_map.erase(model_track); + + // Recurse to child tracks + BOOST_FOREACH(shared_ptr child, + model_track->get_child_tracks()) + search_orphaned_tracks_in_branch(child, orphan_track_map); +} + shared_ptr TimelineWidget::lookup_timeline_track( shared_ptr model_track) const @@ -378,7 +427,32 @@ TimelineWidget::lookup_timeline_track( ENSURE(iterator->second != NULL); return iterator->second; } + +boost::shared_ptr +TimelineWidget::lookup_model_track( + const timeline::Track *timeline_track) const +{ + REQUIRE(sequence); + std::pair, shared_ptr > + pair; + BOOST_FOREACH( pair, trackMap ) + { + if(pair.second.get() == timeline_track) + { + ENSURE(pair.first); + return pair.first; + } + } + + // The track is not present in the map + // We are in an error condition if the timeline track is not found + // - the timeline tracks must always be synchronous with the model + // tracks. + ENSURE(0); + return shared_ptr(); +} + void TimelineWidget::update_scroll() { diff --git a/src/gui/widgets/timeline-widget.hpp b/src/gui/widgets/timeline-widget.hpp index 0e379eb11..41ad86b75 100644 --- a/src/gui/widgets/timeline-widget.hpp +++ b/src/gui/widgets/timeline-widget.hpp @@ -191,10 +191,21 @@ private: * @return The timeline track created, or an empty shared_ptr if * model_track has an unreckognised type (this is an error condition). **/ - static boost::shared_ptr + boost::shared_ptr create_timeline_track_from_model_track( boost::shared_ptr model_track); + /** + * Removes any UI tracks which no longer have corresponding model + * tracks present in the sequence. + **/ + void remove_orphaned_tracks(); + + void search_orphaned_tracks_in_branch( + boost::shared_ptr model_track, + std::map, + boost::shared_ptr > &orphan_track_map); + /** * Looks up a timeline UI track in trackMap that corresponds to a * given model_track. @@ -205,6 +216,17 @@ private: **/ boost::shared_ptr lookup_timeline_track( boost::shared_ptr model_track) const; + + /** + * Looks up a model track in trackMap that corresponds to a + * given timeline track. + * @param timeline_track The timeline UI track to look up. + * @returns The model track found, or an empty shared_ptr if + * timeline_track has no corresponding timeline UI track (this is an + * error condition). + **/ + boost::shared_ptr lookup_model_track( + const timeline::Track *timeline_track) const; // ----- Layout Functions ----- // @@ -305,6 +327,7 @@ protected: friend class timeline::Tool; friend class timeline::ArrowTool; friend class timeline::IBeamTool; + friend class timeline::Track; }; } // namespace widgets diff --git a/src/gui/widgets/timeline/timeline-clip-track.cpp b/src/gui/widgets/timeline/timeline-clip-track.cpp index 8e9e0bd2d..c5d384bb0 100644 --- a/src/gui/widgets/timeline/timeline-clip-track.cpp +++ b/src/gui/widgets/timeline/timeline-clip-track.cpp @@ -29,7 +29,8 @@ namespace gui { namespace widgets { namespace timeline { -ClipTrack::ClipTrack() +ClipTrack::ClipTrack(TimelineWidget &timeline_widget) : + Track(timeline_widget) { } diff --git a/src/gui/widgets/timeline/timeline-clip-track.hpp b/src/gui/widgets/timeline/timeline-clip-track.hpp index 0100763a3..5b5b33e75 100644 --- a/src/gui/widgets/timeline/timeline-clip-track.hpp +++ b/src/gui/widgets/timeline/timeline-clip-track.hpp @@ -41,7 +41,7 @@ class TimelineViewWindow; class ClipTrack : public timeline::Track { public: - ClipTrack(); + ClipTrack(TimelineWidget &timeline_widget); void draw_track(Cairo::RefPtr cairo, TimelineViewWindow* const window) const; diff --git a/src/gui/widgets/timeline/timeline-group-track.cpp b/src/gui/widgets/timeline/timeline-group-track.cpp index 49c1077f1..570095bb1 100644 --- a/src/gui/widgets/timeline/timeline-group-track.cpp +++ b/src/gui/widgets/timeline/timeline-group-track.cpp @@ -28,7 +28,8 @@ namespace gui { namespace widgets { namespace timeline { -GroupTrack::GroupTrack() +GroupTrack::GroupTrack(TimelineWidget &timeline_widget) : + Track(timeline_widget) { } diff --git a/src/gui/widgets/timeline/timeline-group-track.hpp b/src/gui/widgets/timeline/timeline-group-track.hpp index 5e2368a54..46e0fdef7 100644 --- a/src/gui/widgets/timeline/timeline-group-track.hpp +++ b/src/gui/widgets/timeline/timeline-group-track.hpp @@ -36,7 +36,7 @@ namespace timeline { class GroupTrack : public timeline::Track { public: - GroupTrack(); + GroupTrack(TimelineWidget &timeline_widget); void draw_track(Cairo::RefPtr cairo, TimelineViewWindow* constwindow) diff --git a/src/gui/widgets/timeline/timeline-header-container.cpp b/src/gui/widgets/timeline/timeline-header-container.cpp index e5b58d486..506eb0316 100644 --- a/src/gui/widgets/timeline/timeline-header-container.cpp +++ b/src/gui/widgets/timeline/timeline-header-container.cpp @@ -150,11 +150,25 @@ bool TimelineHeaderContainer::on_button_press_event ( break; case 3: // Right Click - // Popup the context menu - contextMenu.popup(event->button, event->time); - break; - - + { + // Popup the context menu + shared_ptr header = header_from_point( + Gdk::Point(event->x, event->y)); + + // Are we hovering on a header? + if(header) + { + // Yes - show the header's context menu + header->show_header_context_menu( + event->button, event->time); + } + else + { + // No - show the default context menu + contextMenu.popup(event->button, event->time); + } + break; + } } return true; @@ -239,6 +253,12 @@ TimelineHeaderContainer::forall_vfunc(gboolean /* include_internals */, } } +void +TimelineHeaderContainer::on_remove(Widget* widget) +{ + // Do nothing - this is just to keep Gtk::Container happy +} + bool TimelineHeaderContainer::on_expose_event(GdkEventExpose *event) { @@ -477,6 +497,25 @@ TimelineHeaderContainer::draw_header_decoration( draw_header_decoration(child, clip_rect); } +boost::shared_ptr +TimelineHeaderContainer::header_from_point(const Gdk::Point &point) +{ + std::pair, Gdk::Rectangle> pair; + BOOST_FOREACH( pair, headerBoxes ) + { + // Hit test the rectangle + const Gdk::Rectangle &rect = pair.second; + + if(point.get_x() >= rect.get_x() && + point.get_x() < rect.get_x() + rect.get_width() && + point.get_y() >= rect.get_y() && + point.get_y() < rect.get_y() + rect.get_height()) + return pair.first; + } + + return shared_ptr(); +} + shared_ptr TimelineHeaderContainer::expander_button_from_point( const Gdk::Point &point) diff --git a/src/gui/widgets/timeline/timeline-header-container.hpp b/src/gui/widgets/timeline/timeline-header-container.hpp index a035e104a..517ed3bce 100644 --- a/src/gui/widgets/timeline/timeline-header-container.hpp +++ b/src/gui/widgets/timeline/timeline-header-container.hpp @@ -118,6 +118,12 @@ private: **/ void forall_vfunc(gboolean include_internals, GtkCallback callback, gpointer callback_data); + + /** + * An event handler that is called when a widget is removed from the + * container. + **/ + void on_remove(Widget* widget); /* ===== Events ===== */ private: @@ -193,6 +199,9 @@ private: void draw_header_decoration( boost::shared_ptr model_track, const Gdk::Rectangle &clip_rect); + + boost::shared_ptr header_from_point( + const Gdk::Point &point); /** * Given a point, expander_button_from_point finds the track of the @@ -297,6 +306,8 @@ private: * in pixels. **/ int expand_button_size; + + friend class timeline::Track; }; } // namespace timeline diff --git a/src/gui/widgets/timeline/timeline-track.cpp b/src/gui/widgets/timeline/timeline-track.cpp index 6cf2ae95f..05f49b523 100644 --- a/src/gui/widgets/timeline/timeline-track.cpp +++ b/src/gui/widgets/timeline/timeline-track.cpp @@ -24,15 +24,18 @@ #include #include "timeline-track.hpp" +#include "../timeline-widget.hpp" #include "../../window-manager.hpp" +using namespace boost; using namespace Gtk; namespace gui { namespace widgets { namespace timeline { -Track::Track() : +Track::Track(TimelineWidget &timeline_widget) : + timelineWidget(timeline_widget), expanded(true), enableButton(Gtk::StockID("track_enabled")), lockButton(Gtk::StockID("track_unlocked")) @@ -54,6 +57,14 @@ Track::Track() : headerWidget.pack_start(titleBox, PACK_SHRINK); headerWidget.pack_start(buttonBar, PACK_SHRINK); + + // Setup the context menu + Menu::MenuList& menu_list = contextMenu.items(); + menu_list.push_back( Menu_Helpers::MenuElem(_("_Add Track"), + sigc::mem_fun(timelineWidget, + &TimelineWidget::on_add_track_command) ) ); + menu_list.push_back( Menu_Helpers::MenuElem(_("_Remove Track"), + sigc::mem_fun(this, &Track::on_remove_track) ) ); } Gtk::Widget& @@ -80,6 +91,23 @@ Track::set_expanded(bool expanded) this->expanded = expanded; } +void +Track::show_header_context_menu(guint button, guint32 time) +{ + contextMenu.popup(button, time); +} + +void +Track::on_remove_track() +{ + shared_ptr model_track = + timelineWidget.lookup_model_track(this); + ASSERT(model_track); + ASSERT(timelineWidget.sequence); + + timelineWidget.sequence->get_child_track_list().remove(model_track); +} + } // namespace timeline } // namespace widgets } // namespace gui diff --git a/src/gui/widgets/timeline/timeline-track.hpp b/src/gui/widgets/timeline/timeline-track.hpp index 2c5aff97c..d5ad70538 100644 --- a/src/gui/widgets/timeline/timeline-track.hpp +++ b/src/gui/widgets/timeline/timeline-track.hpp @@ -25,6 +25,7 @@ #include "../../gtk-lumiera.hpp" #include "../../model/track.hpp" +#include "timeline-header-container.hpp" #ifndef TIMELINE_TRACK_HPP #define TIMELINE_TRACK_HPP @@ -38,7 +39,7 @@ class TimelineViewWindow; class Track { public: - Track(); + Track(TimelineWidget &timeline_widget); Gtk::Widget& get_header_widget(); @@ -47,12 +48,19 @@ public: bool get_expanded() const; void set_expanded(bool expanded); + + void show_header_context_menu(guint button, guint32 time); virtual void draw_track(Cairo::RefPtr cairo, TimelineViewWindow* const window) const = 0; private: + void on_remove_track(); + +private: + + TimelineWidget &timelineWidget; bool expanded; @@ -65,6 +73,8 @@ private: Gtk::Entry titleBox; Gtk::Toolbar buttonBar; + + Gtk::Menu contextMenu; }; From c536915b2ea925f4b8bd7296e90506ccd7ec96d6 Mon Sep 17 00:00:00 2001 From: Joel Holdsworth Date: Sat, 20 Dec 2008 15:55:46 +0000 Subject: [PATCH 023/214] Corrected errors introduced by the merge --- src/backend/Makefile.am | 3 ++- src/gui/Makefile.am | 2 +- src/gui/model/parent-track.hpp | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/backend/Makefile.am b/src/backend/Makefile.am index a05e0e9b6..913c9d6f8 100644 --- a/src/backend/Makefile.am +++ b/src/backend/Makefile.am @@ -19,7 +19,8 @@ liblumierabackend_la_srcdir = $(top_srcdir)/src/backend lib_LTLIBRARIES += liblumierabackend.la liblumierabackend_la_CPPFLAGS = $(AM_CPPFLAGS) -liblumierabackend_la_CFLAGS = $(AM_CFLAGS) -std=gnu99 -Wextra -Wall -Werror +liblumierabackend_la_CFLAGS = $(AM_CFLAGS) -std=gnu99 -Wextra -Wall +#liblumierabackend_la_CFLAGS = $(AM_CFLAGS) -std=gnu99 -Wextra -Wall -Werror liblumierabackend_la_LIBADD = liblumiera.la liblumierabackend_la_SOURCES = \ diff --git a/src/gui/Makefile.am b/src/gui/Makefile.am index 6fd571181..8468c566e 100644 --- a/src/gui/Makefile.am +++ b/src/gui/Makefile.am @@ -82,7 +82,7 @@ libgui_la_CPPFLAGS = $(AM_CPPFLAGS) \ -DPACKAGE_DATA_DIR=\""$(datadir)"\" \ $(LUMIERA_GUI_CFLAGS) -lumigui_SOURCES = \ +libgui_la_SOURCES = \ $(lumigui_srcdir)/gtk-lumiera.cpp \ $(lumigui_srcdir)/gtk-lumiera.hpp \ $(lumigui_srcdir)/window-manager.cpp \ diff --git a/src/gui/model/parent-track.hpp b/src/gui/model/parent-track.hpp index 518140d9f..bc697d903 100644 --- a/src/gui/model/parent-track.hpp +++ b/src/gui/model/parent-track.hpp @@ -26,7 +26,7 @@ */ #include "track.hpp" -#include "../../common/observable-list.hpp" +#include "../../lib/observable-list.hpp" #ifndef PARENT_TRACK_HPP #define PARENT_TRACK_HPP From 34077ca41cea577092ed2e8c162272b21e4e1051 Mon Sep 17 00:00:00 2001 From: Christian Thaeter Date: Sun, 21 Dec 2008 18:22:19 +0100 Subject: [PATCH 024/214] rename gtkgui.lum to gtk_gui.lum --- src/gui/Makefile.am | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/gui/Makefile.am b/src/gui/Makefile.am index 21ef3889a..fed36ad88 100644 --- a/src/gui/Makefile.am +++ b/src/gui/Makefile.am @@ -51,15 +51,15 @@ lumigui_DEPENDENCIES = \ $(top_builddir)/liblumieraproc.la # -# gtkgui.lum becomes the pluginized gu +# gtk_gui.lum becomes the pluginized gui # -pkglib_LTLIBRARIES += gtkgui.la +pkglib_LTLIBRARIES += gtk_gui.la -gtkgui_la_CPPFLAGS = $(AM_CPPFLAGS) -Wall -Werror -DLUMIERA_PLUGIN -I$(top_srcdir)/src/ -gtkgui_la_LDFLAGS = -module -avoid-version -no-undefined -rpath /dev/null -shrext .lum +gtk_gui_la_CPPFLAGS = $(AM_CPPFLAGS) -Wall -Werror -DLUMIERA_PLUGIN -I$(top_srcdir)/src/ +gtk_gui_la_LDFLAGS = -module -avoid-version -no-undefined -rpath /dev/null -shrext .lum -gtkgui_la_LIBADD = \ +gtk_gui_la_LIBADD = \ liblumieracommon.la \ liblumierabackend.la \ liblumieraproc.la \ @@ -67,12 +67,12 @@ gtkgui_la_LIBADD = \ $(LUMIERA_GUI_LIBS) \ $(NOBUGMT_LUMIERA_LIBS) -gtkgui_la_SOURCES = \ +gtk_gui_la_SOURCES = \ $(lumigui_srcdir)/guistart.cpp # -# libgui is a convenience library used by lumigui and the gtkgui module +# libgui is a convenience library used by lumigui and the gtk_gui module # noinst_LTLIBRARIES += libgui.la From 1058454871301d390fbb0056df419d6ffa5562e5 Mon Sep 17 00:00:00 2001 From: Christian Thaeter Date: Sun, 21 Dec 2008 18:59:34 +0100 Subject: [PATCH 025/214] remove cuckoo from the build system cuckoo hashing was replaced by the psplay lookups, it needs some improvements to make it easier useable and better hash function for strings. This will be done someday later. --- src/lib/Makefile.am | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am index b8e1a44fb..e603e2ce4 100644 --- a/src/lib/Makefile.am +++ b/src/lib/Makefile.am @@ -28,7 +28,6 @@ liblumiera_la_SOURCES = \ $(liblumiera_la_srcdir)/condition.c \ $(liblumiera_la_srcdir)/luid.c \ $(liblumiera_la_srcdir)/safeclib.c \ - $(liblumiera_la_srcdir)/cuckoo.c \ $(liblumiera_la_srcdir)/psplay.c \ $(liblumiera_la_srcdir)/mrucache.c \ $(liblumiera_la_srcdir)/time.c \ @@ -50,7 +49,6 @@ noinst_HEADERS += \ $(liblumiera_la_srcdir)/condition.h \ $(liblumiera_la_srcdir)/luid.h \ $(liblumiera_la_srcdir)/safeclib.h \ - $(liblumiera_la_srcdir)/cuckoo.h \ $(liblumiera_la_srcdir)/psplay.h \ $(liblumiera_la_srcdir)/mrucache.h \ $(liblumiera_la_srcdir)/time.h \ From 505869767ecdebbafc900f0b0ea59c3d511465b0 Mon Sep 17 00:00:00 2001 From: Christian Thaeter Date: Sun, 21 Dec 2008 21:15:11 +0100 Subject: [PATCH 026/214] Fix config path for tests --- tests/31plugin.tests | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/31plugin.tests b/tests/31plugin.tests index d3e333408..15f7e7a90 100644 --- a/tests/31plugin.tests +++ b/tests/31plugin.tests @@ -7,6 +7,7 @@ return: 0 END export LUMIERA_PLUGIN_PATH=.libs +export LUMIERA_CONFIG_PATH=./ TEST "discovering plugins" plugin_discover < Date: Mon, 22 Dec 2008 02:23:11 +0100 Subject: [PATCH 027/214] mixed fixes of small issues (compiler warnings) --- src/backend/filedescriptor.c | 2 +- src/lib/psplay.c | 4 ++-- src/lib/safeclib.c | 1 + 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/backend/filedescriptor.c b/src/backend/filedescriptor.c index f2c35beee..906fdc3cd 100644 --- a/src/backend/filedescriptor.c +++ b/src/backend/filedescriptor.c @@ -299,7 +299,7 @@ lumiera_filedescriptor_delete (LumieraFiledescriptor self, const char* name) { TRACE (filedescriptor, "truncate %s to %lld", name, self->realsize); lumiera_filehandlecache_checkout (lumiera_fhcache, self->handle); - ftruncate (lumiera_filehandle_handle (self->handle), self->realsize); + (void) ftruncate (lumiera_filehandle_handle (self->handle), self->realsize); lumiera_filehandlecache_checkin (lumiera_fhcache, self->handle); } diff --git a/src/lib/psplay.c b/src/lib/psplay.c index 1d2d4dd27..2fc38e75c 100644 --- a/src/lib/psplay.c +++ b/src/lib/psplay.c @@ -290,7 +290,7 @@ psplay_insert (PSplay self, PSplaynode node, int splayfactor) } } ++self->elem_cnt; - if (self->elem_cnt >= 1<log2) ++self->log2; + if (self->elem_cnt >= 1UL<log2) ++self->log2; if (splayfactor && trail.depth > 2) psplay_splay (self, &trail, splayfactor); return node; @@ -384,7 +384,7 @@ psplay_remove (PSplay self, PSplaynode node) *r = i; } --self->elem_cnt; - if (self->elem_cnt < 1<log2) --self->log2; + if (self->elem_cnt < 1UL<log2) --self->log2; return node; } diff --git a/src/lib/safeclib.c b/src/lib/safeclib.c index 7f8f79eb2..ce099ccc9 100644 --- a/src/lib/safeclib.c +++ b/src/lib/safeclib.c @@ -107,6 +107,7 @@ lumiera_tmpbuf_freeall (void); static void lumiera_tmpbuf_destroy (void* buf) { + (void) buf; lumiera_tmpbuf_freeall (); } From 4fb8f5b69db2d9ea268e334bc999fbad32c448cf Mon Sep 17 00:00:00 2001 From: Christian Thaeter Date: Mon, 22 Dec 2008 02:24:19 +0100 Subject: [PATCH 028/214] Makefile.am makeover, add CFLAGS and CXXFLAGS everywhere --- src/common/Makefile.am | 1 + src/gui/Makefile.am | 10 ++++- src/lib/Makefile.am | 3 +- src/lumiera/Makefile.am | 3 +- src/proc/Makefile.am | 98 ++++++++++++++++++++++------------------- src/tool/Makefile.am | 2 +- 6 files changed, 68 insertions(+), 49 deletions(-) diff --git a/src/common/Makefile.am b/src/common/Makefile.am index 244f21f53..5833b9ba1 100644 --- a/src/common/Makefile.am +++ b/src/common/Makefile.am @@ -20,6 +20,7 @@ lib_LTLIBRARIES += liblumieracommon.la liblumieracommon_la_CPPFLAGS = $(AM_CPPFLAGS) -DLUMIERA_CONFIG_PATH="\"$(pkgdatadir)/config\"" -DLUMIERA_PLUGIN_PATH="\"$(pkglibdir)/\"" liblumieracommon_la_CFLAGS = $(AM_CFLAGS) -std=gnu99 -Wextra -Wall -Werror +liblumieracommon_la_CXXFLAGS = $(AM_CXXFLAGS) -Wextra -Wall liblumieracommon_la_LIBADD = liblumiera.la liblumieracommon_la_SOURCES = \ diff --git a/src/gui/Makefile.am b/src/gui/Makefile.am index fed36ad88..fb73e3d29 100644 --- a/src/gui/Makefile.am +++ b/src/gui/Makefile.am @@ -28,6 +28,9 @@ lumigui_CPPFLAGS = $(AM_CPPFLAGS) \ -DPACKAGE_DATA_DIR=\""$(datadir)"\" \ $(LUMIERA_GUI_CFLAGS) +lumigui_CFLAGS = $(AM_CFLAGS) -std=gnu99 -Wall -Wextra -Werror +lumigui_CXXFLAGS = $(AM_CXXFLAGS) -Wall -Wextra + lumigui_LDADD = \ liblumieracommon.la \ liblumierabackend.la \ @@ -56,7 +59,9 @@ lumigui_DEPENDENCIES = \ pkglib_LTLIBRARIES += gtk_gui.la -gtk_gui_la_CPPFLAGS = $(AM_CPPFLAGS) -Wall -Werror -DLUMIERA_PLUGIN -I$(top_srcdir)/src/ +gtk_gui_la_CFLAGS = $(AM_CFLAGS) -std=gnu99 -Wall -Wextra -Werror +gtk_gui_la_CXXFLAGS = $(AM_CXXFLAGS) -Wall -Wextra +gtk_gui_la_CPPFLAGS = $(AM_CPPFLAGS) -DLUMIERA_PLUGIN -I$(top_srcdir)/src/ gtk_gui_la_LDFLAGS = -module -avoid-version -no-undefined -rpath /dev/null -shrext .lum gtk_gui_la_LIBADD = \ @@ -76,6 +81,9 @@ gtk_gui_la_SOURCES = \ # noinst_LTLIBRARIES += libgui.la +libgui_la_CFLAGS = $(AM_CFLAGS) -std=gnu99 -Wall -Wextra -Werror +libgui_la_CXXFLAGS = $(AM_CXXFLAGS) -Wall -Wextra + libgui_la_CPPFLAGS = $(AM_CPPFLAGS) \ -DPACKAGE_LOCALE_DIR=\""$(prefix)/$(DATADIRNAME)/locale"\" \ -DPACKAGE_SRC_DIR=\""$(srcdir)"\" \ diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am index e603e2ce4..4608feedb 100644 --- a/src/lib/Makefile.am +++ b/src/lib/Makefile.am @@ -18,7 +18,8 @@ liblumiera_la_srcdir = $(top_srcdir)/src/lib lib_LTLIBRARIES += liblumiera.la -liblumiera_la_CFLAGS = $(CFLAGS) -std=gnu99 -Wall -Werror +liblumiera_la_CFLAGS = $(AM_CFLAGS) -std=gnu99 -Wall -Wextra -Werror +liblumiera_la_CXXFLAGS = $(AM_CXXFLAGS) -Wall -Wextra liblumiera_la_SOURCES = \ $(liblumiera_la_srcdir)/error.c \ diff --git a/src/lumiera/Makefile.am b/src/lumiera/Makefile.am index 62a9b00df..4a5488971 100644 --- a/src/lumiera/Makefile.am +++ b/src/lumiera/Makefile.am @@ -19,7 +19,8 @@ lumiera_srcdir = $(top_srcdir)/src/lumiera bin_PROGRAMS += lumiera lumiera_CPPFLAGS = $(AM_CPPFLAGS) -lumiera_CFLAGS = $(AM_CFLAGS) -std=gnu99 -Wextra -Wall -Werror +lumiera_CFLAGS = $(AM_CFLAGS) -std=gnu99 -Wall -Wextra -Werror +lumiera_CXXFLAGS = $(AM_CXXFLAGS) -Wall -Wextra lumiera_LDADD = \ liblumieracommon.la \ diff --git a/src/proc/Makefile.am b/src/proc/Makefile.am index 464da33d9..c0058adfa 100644 --- a/src/proc/Makefile.am +++ b/src/proc/Makefile.am @@ -21,7 +21,8 @@ liblumiproc_la_srcdir = $(top_srcdir)/src/proc noinst_LTLIBRARIES += liblumiproc.la -liblumiproc_la_CXXFLAGS = $(CXXFLAGS) -Wall +liblumiproc_la_CFLAGS = $(AM_CFLAGS) -std=gnu99 -Wall -Wextra -Werror +liblumiproc_la_CXXFLAGS = $(AM_CXXFLAGS) -Wall -Wextra liblumiproc_la_SOURCES = \ $(liblumiproc_la_srcdir)/controllerfacade.cpp \ @@ -35,13 +36,14 @@ liblumiproc_la_SOURCES = \ liblumiprocasset_la_srcdir = $(top_srcdir)/src/proc/asset noinst_LTLIBRARIES += liblumiprocasset.la -liblumiprocasset_la_CXXFLAGS = $(CXXFLAGS) -Wall +liblumiprocasset_la_CFLAGS = $(AM_CFLAGS) -std=gnu99 -Wall -Wextra -Werror +liblumiprocasset_la_CXXFLAGS = $(AM_CXXFLAGS) -Wall -Wextra liblumiprocasset_la_SOURCES = \ $(liblumiprocasset_la_srcdir)/codec.cpp \ $(liblumiprocasset_la_srcdir)/compoundmedia.cpp \ $(liblumiprocasset_la_srcdir)/dataset.cpp \ - $(liblumiprocasset_la_srcdir)/effect.cpp \ + $(liblumiprocasset_la_srcdir)/effect.cpp \ $(liblumiprocasset_la_srcdir)/preview.cpp \ $(liblumiprocasset_la_srcdir)/unknown.cpp \ $(liblumiprocasset_la_srcdir)/clip.cpp \ @@ -51,7 +53,7 @@ liblumiprocasset_la_SOURCES = \ $(liblumiprocasset_la_srcdir)/pipe.cpp \ $(liblumiprocasset_la_srcdir)/proc.cpp \ $(liblumiprocasset_la_srcdir)/procpatt.cpp \ - $(liblumiprocasset_la_srcdir)/struct.cpp \ + $(liblumiprocasset_la_srcdir)/struct.cpp \ $(liblumiprocasset_la_srcdir)/track.cpp @@ -59,33 +61,35 @@ liblumiprocasset_la_SOURCES = \ liblumiprocengine_la_srcdir = $(top_srcdir)/src/proc/engine noinst_LTLIBRARIES += liblumiprocengine.la -liblumiprocengine_la_CXXFLAGS = $(CXXFLAGS) -Wall +liblumiprocengine_la_CFLAGS = $(AM_CFLAGS) -std=gnu99 -Wall -Wextra -Werror +liblumiprocengine_la_CXXFLAGS = $(AM_CXXFLAGS) -Wall -Wextra -liblumiprocengine_la_SOURCES = \ - $(liblumiprocengine_la_srcdir)/buffhandle.cpp \ - $(liblumiprocengine_la_srcdir)/link.cpp \ - $(liblumiprocengine_la_srcdir)/mask.cpp \ - $(liblumiprocengine_la_srcdir)/nodefactory.cpp \ - $(liblumiprocengine_la_srcdir)/nodewiring.cpp \ - $(liblumiprocengine_la_srcdir)/pluginadapter.cpp \ - $(liblumiprocengine_la_srcdir)/processor.cpp \ - $(liblumiprocengine_la_srcdir)/procnode.cpp \ - $(liblumiprocengine_la_srcdir)/projector.cpp \ - $(liblumiprocengine_la_srcdir)/renderengine.cpp \ - $(liblumiprocengine_la_srcdir)/source.cpp \ - $(liblumiprocengine_la_srcdir)/stateproxy.cpp \ - $(liblumiprocengine_la_srcdir)/trafo.cpp +liblumiprocengine_la_SOURCES = \ + $(liblumiprocengine_la_srcdir)/buffhandle.cpp \ + $(liblumiprocengine_la_srcdir)/link.cpp \ + $(liblumiprocengine_la_srcdir)/mask.cpp \ + $(liblumiprocengine_la_srcdir)/nodefactory.cpp \ + $(liblumiprocengine_la_srcdir)/nodewiring.cpp \ + $(liblumiprocengine_la_srcdir)/pluginadapter.cpp \ + $(liblumiprocengine_la_srcdir)/processor.cpp \ + $(liblumiprocengine_la_srcdir)/procnode.cpp \ + $(liblumiprocengine_la_srcdir)/projector.cpp \ + $(liblumiprocengine_la_srcdir)/renderengine.cpp \ + $(liblumiprocengine_la_srcdir)/source.cpp \ + $(liblumiprocengine_la_srcdir)/stateproxy.cpp \ + $(liblumiprocengine_la_srcdir)/trafo.cpp liblumiprocmobject_la_srcdir = $(top_srcdir)/src/proc/mobject noinst_LTLIBRARIES += liblumiprocmobject.la -liblumiprocmobject_la_CXXFLAGS = $(CXXFLAGS) -Wall +liblumiprocmobject_la_CFLAGS = $(AM_CFLAGS) -std=gnu99 -Wall -Wextra -Werror +liblumiprocmobject_la_CXXFLAGS = $(AM_CXXFLAGS) -Wall -Wextra liblumiprocmobject_la_SOURCES = \ $(liblumiprocmobject_la_srcdir)/builderfacade.cpp \ - $(liblumiprocmobject_la_srcdir)/interpolator.cpp \ + $(liblumiprocmobject_la_srcdir)/interpolator.cpp \ $(liblumiprocmobject_la_srcdir)/mobject.cpp \ $(liblumiprocmobject_la_srcdir)/parameter.cpp \ $(liblumiprocmobject_la_srcdir)/paramprovider.cpp \ @@ -96,7 +100,8 @@ liblumiprocmobject_la_SOURCES = \ liblumiprocmobjectbuilder_la_srcdir = $(top_srcdir)/src/proc/mobject/builder noinst_LTLIBRARIES += liblumiprocmobjectbuilder.la -liblumiprocmobjectbuilder_la_CXXFLAGS = $(CXXFLAGS) -Wall +liblumiprocmobjectbuilder_la_CFLAGS = $(AM_CFLAGS) -std=gnu99 -Wall -Wextra -Werror +liblumiprocmobjectbuilder_la_CXXFLAGS = $(AM_CXXFLAGS) -Wall -Wextra liblumiprocmobjectbuilder_la_SOURCES = \ $(liblumiprocmobjectbuilder_la_srcdir)/assembler.cpp \ @@ -109,17 +114,19 @@ liblumiprocmobjectbuilder_la_SOURCES = \ liblumiproccontrol_la_srcdir = $(top_srcdir)/src/proc/control noinst_LTLIBRARIES += liblumiproccontrol.la -liblumiproccontrol_la_CXXFLAGS = $(CXXFLAGS) -Wall +liblumiproccontrol_la_CFLAGS = $(AM_CFLAGS) -std=gnu99 -Wall -Wextra -Werror +liblumiproccontrol_la_CXXFLAGS = $(AM_CXXFLAGS) -Wall -Wextra -liblumiproccontrol_la_SOURCES = \ - $(liblumiproccontrol_la_srcdir)/pathmanager.cpp \ +liblumiproccontrol_la_SOURCES = \ + $(liblumiproccontrol_la_srcdir)/pathmanager.cpp \ $(liblumiproccontrol_la_srcdir)/stypemanager.cpp liblumiprocmobjectsession_la_srcdir = $(top_srcdir)/src/proc/mobject/session noinst_LTLIBRARIES += liblumiprocmobjectsession.la -liblumiprocmobjectsession_la_CXXFLAGS = $(CXXFLAGS) -Wall +liblumiprocmobjectsession_la_CFLAGS = $(AM_CFLAGS) -std=gnu99 -Wall -Wextra -Werror +liblumiprocmobjectsession_la_CXXFLAGS = $(AM_CXXFLAGS) -Wall -Wextra liblumiprocmobjectsession_la_SOURCES = \ $(liblumiprocmobjectsession_la_srcdir)/abstractmo.cpp \ @@ -130,8 +137,8 @@ liblumiprocmobjectsession_la_SOURCES = \ $(liblumiprocmobjectsession_la_srcdir)/constraint.cpp \ $(liblumiprocmobjectsession_la_srcdir)/defsmanager.cpp \ $(liblumiprocmobjectsession_la_srcdir)/effect.cpp \ - $(liblumiprocmobjectsession_la_srcdir)/fixedlocation.cpp \ - $(liblumiprocmobjectsession_la_srcdir)/label.cpp \ + $(liblumiprocmobjectsession_la_srcdir)/fixedlocation.cpp \ + $(liblumiprocmobjectsession_la_srcdir)/label.cpp \ $(liblumiprocmobjectsession_la_srcdir)/meta.cpp \ $(liblumiprocmobjectsession_la_srcdir)/relativelocation.cpp \ $(liblumiprocmobjectsession_la_srcdir)/segment.cpp \ @@ -141,7 +148,7 @@ liblumiprocmobjectsession_la_SOURCES = \ $(liblumiprocmobjectsession_la_srcdir)/sessmanagerimpl.cpp \ $(liblumiprocmobjectsession_la_srcdir)/edl.cpp \ $(liblumiprocmobjectsession_la_srcdir)/session.cpp \ - $(liblumiprocmobjectsession_la_srcdir)/track.cpp \ + $(liblumiprocmobjectsession_la_srcdir)/track.cpp \ $(liblumiprocmobjectsession_la_srcdir)/fixture.cpp \ $(liblumiprocmobjectsession_la_srcdir)/locatingpin.cpp \ $(liblumiprocmobjectsession_la_srcdir)/mobjectfactory.cpp \ @@ -153,39 +160,39 @@ liblumiprocmobjectsession_la_SOURCES = \ noinst_HEADERS += \ $(liblumiproc_la_srcdir)/asset/category.hpp \ $(liblumiproc_la_srcdir)/asset/clip.hpp \ - $(liblumiproc_la_srcdir)/asset/codec.hpp \ - $(liblumiproc_la_srcdir)/asset/compoundmedia.hpp \ + $(liblumiproc_la_srcdir)/asset/codec.hpp \ + $(liblumiproc_la_srcdir)/asset/compoundmedia.hpp \ $(liblumiproc_la_srcdir)/asset/dataset.hpp \ $(liblumiproc_la_srcdir)/asset/effect.hpp \ $(liblumiproc_la_srcdir)/asset/preview.hpp \ $(liblumiproc_la_srcdir)/asset/db.hpp \ - $(liblumiproc_la_srcdir)/asset/buildinstruct.hpp \ - $(liblumiproc_la_srcdir)/asset/media.hpp \ + $(liblumiproc_la_srcdir)/asset/buildinstruct.hpp \ + $(liblumiproc_la_srcdir)/asset/media.hpp \ $(liblumiproc_la_srcdir)/asset/meta.hpp \ $(liblumiproc_la_srcdir)/asset/pipe.hpp \ $(liblumiproc_la_srcdir)/asset/proc.hpp \ $(liblumiproc_la_srcdir)/asset/procpatt.hpp \ $(liblumiproc_la_srcdir)/asset/struct.hpp \ $(liblumiproc_la_srcdir)/asset/structfactoryimpl.hpp \ - $(liblumiproc_la_srcdir)/asset/track.hpp \ + $(liblumiproc_la_srcdir)/asset/track.hpp \ $(liblumiproc_la_srcdir)/asset/unknown.hpp \ $(liblumiproc_la_srcdir)/controllerfacade.hpp \ - $(liblumiproc_la_srcdir)/engine/mask.hpp \ + $(liblumiproc_la_srcdir)/engine/mask.hpp \ $(liblumiproc_la_srcdir)/engine/pluginadapter.hpp \ $(liblumiproc_la_srcdir)/engine/procnode.hpp \ $(liblumiproc_la_srcdir)/engine/projector.hpp \ - $(liblumiproc_la_srcdir)/engine/renderengine.hpp \ + $(liblumiproc_la_srcdir)/engine/renderengine.hpp \ $(liblumiproc_la_srcdir)/engine/source.hpp \ $(liblumiproc_la_srcdir)/engine/trafo.hpp \ $(liblumiproc_la_srcdir)/engine/processor.hpp \ $(liblumiproc_la_srcdir)/mobject/builder/assembler.hpp \ - $(liblumiproc_la_srcdir)/mobject/builder/buildertool.hpp \ + $(liblumiproc_la_srcdir)/mobject/builder/buildertool.hpp \ $(liblumiproc_la_srcdir)/mobject/builder/conmanager.hpp \ $(liblumiproc_la_srcdir)/mobject/builder/segmentationtool.hpp \ - $(liblumiproc_la_srcdir)/mobject/builder/toolfactory.hpp \ + $(liblumiproc_la_srcdir)/mobject/builder/toolfactory.hpp \ $(liblumiproc_la_srcdir)/mobject/builderfacade.hpp \ - $(liblumiproc_la_srcdir)/control/pathmanager.hpp \ - $(liblumiproc_la_srcdir)/control/renderstate.hpp \ + $(liblumiproc_la_srcdir)/control/pathmanager.hpp \ + $(liblumiproc_la_srcdir)/control/renderstate.hpp \ $(liblumiproc_la_srcdir)/mobject/interpolator.hpp \ $(liblumiproc_la_srcdir)/mobject/parameter.hpp \ $(liblumiproc_la_srcdir)/mobject/paramprovider.hpp \ @@ -205,12 +212,12 @@ noinst_HEADERS += \ $(liblumiproc_la_srcdir)/mobject/session/wish.hpp \ $(liblumiproc_la_srcdir)/mobject/session/clip.hpp \ $(liblumiproc_la_srcdir)/mobject/session/constraint.hpp \ - $(liblumiproc_la_srcdir)/mobject/session/defsmanager.hpp \ - $(liblumiproc_la_srcdir)/mobject/session/edl.hpp \ + $(liblumiproc_la_srcdir)/mobject/session/defsmanager.hpp \ + $(liblumiproc_la_srcdir)/mobject/session/edl.hpp \ $(liblumiproc_la_srcdir)/mobject/session/fixture.hpp \ - $(liblumiproc_la_srcdir)/mobject/session/locatingpin.hpp \ + $(liblumiproc_la_srcdir)/mobject/session/locatingpin.hpp \ $(liblumiproc_la_srcdir)/mobject/session/plug.hpp \ - $(liblumiproc_la_srcdir)/mobject/session/sessionimpl.hpp \ + $(liblumiproc_la_srcdir)/mobject/session/sessionimpl.hpp \ $(liblumiproc_la_srcdir)/mobject/session/defsregistry.hpp \ $(liblumiproc_la_srcdir)/mobject/explicitplacement.hpp \ $(liblumiproc_la_srcdir)/mobject/mobject.hpp \ @@ -224,7 +231,8 @@ noinst_HEADERS += \ liblumieraproc_la_srcdir = $(top_srcdir)/src/proc lib_LTLIBRARIES += liblumieraproc.la -liblumieraproc_la_CXXFLAGS = $(CXXFLAGS) -Wall +liblumieraproc_la_CFLAGS = $(AM_CFLAGS) -std=gnu99 -Wall -Wextra -Werror +liblumieraproc_la_CXXFLAGS = $(AM_CXXFLAGS) -Wall -Wextra liblumieraproc_la_SOURCES = diff --git a/src/tool/Makefile.am b/src/tool/Makefile.am index 527964593..64f8fa182 100644 --- a/src/tool/Makefile.am +++ b/src/tool/Makefile.am @@ -20,7 +20,7 @@ lumitool_srcdir = $(top_srcdir)/src/tool noinst_PROGRAMS += luidgen luidgen_CFLAGS = $(CFLAGS) -std=gnu99 -Wall -Werror -luidgen_CPPFLAGS = -I$(top_srcdir)/src/ +luidgen_CPPFLAGS = -I$(top_srcdir)/src/ luidgen_SOURCES = \ $(lumitool_srcdir)/luidgen.c From edea4229aa27fbf5840448256b857585bf65bbe7 Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Mon, 22 Dec 2008 03:54:34 +0100 Subject: [PATCH 029/214] SCons: add missing -Wextra compiler flag --- SConstruct | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SConstruct b/SConstruct index 58b47e4dc..52493aa4b 100644 --- a/SConstruct +++ b/SConstruct @@ -77,7 +77,7 @@ def setupBasicEnvironment(): , ICONDIR=ICONDIR , CPPPATH=["#"+SRCDIR] # used to find includes, "#" means always absolute to build-root , CPPDEFINES=['-DLUMIERA_VERSION='+VERSION ] # note: it's a list to append further defines - , CCFLAGS='-Wall ' # -fdiagnostics-show-option + , CCFLAGS='-Wall -Wextra ' , CFLAGS='-std=gnu99' ) RegisterIcon_Builder(env,SVGRENDERER) From a0ff1f611a28aaed64c04d932fe3d6a75f1100b5 Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Mon, 22 Dec 2008 05:00:02 +0100 Subject: [PATCH 030/214] Try to circumvent problems with creating the Icon directory. Seems to be either concurrency, or a permission problem. --- admin/render-icon.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/admin/render-icon.py b/admin/render-icon.py index 2f5c64592..0f9cee294 100755 --- a/admin/render-icon.py +++ b/admin/render-icon.py @@ -32,10 +32,14 @@ rsvgPath = "./rsvg-convert" artworkLayerPrefix = "artwork:" def createDirectory( name ): - if os.path.isfile(name): - os.remove(name) - if not os.path.exists(name): - os.mkdir(name) + try: + if os.path.isfile(name): + os.remove(name) + if not os.path.exists(name): + os.mkdir(name) + except: + print 'WARNING: createDirectory("%s") failed. Permission problems?' % name + def copyMergeDirectory( src, dst ): listing = os.listdir(src) From d5710ffc54aa788374335ff3d82e9d830c49b9b1 Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Sun, 14 Dec 2008 04:34:40 +0100 Subject: [PATCH 031/214] WIP: draft a test to check monitor object locking --- tests/40components.tests | 5 + tests/common/multithread-locking-test.cpp | 211 ++++++++++++++++++++++ 2 files changed, 216 insertions(+) create mode 100644 tests/common/multithread-locking-test.cpp diff --git a/tests/40components.tests b/tests/40components.tests index 4ff311a4d..c73e24eb1 100644 --- a/tests/40components.tests +++ b/tests/40components.tests @@ -220,6 +220,11 @@ return: 0 END +PLANNED "Multithread Locking by Monitor" MultithreadLocking_test < [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, ] out: removed 0 ---> [ 1, 2, 3, 4, 5, 6, 7, 8, 9, ] diff --git a/tests/common/multithread-locking-test.cpp b/tests/common/multithread-locking-test.cpp new file mode 100644 index 000000000..d03fe5c28 --- /dev/null +++ b/tests/common/multithread-locking-test.cpp @@ -0,0 +1,211 @@ +/* + MultithreadLocking(Test) - check the monitor object based locking + + Copyright (C) Lumiera.org + 2008, Hermann Vosseler + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +* *****************************************************/ + + +#include "common/test/run.hpp" +//#include "common/util.hpp" +#include "common/error.hpp" + +#include "common/multithread.hpp" + +#include + +//#include +//#include +#include + +//using boost::lexical_cast; +//using boost::format; +//using util::isnil; +//using std::string; +using std::cout; +using test::Test; + + +namespace lib { + namespace test { + + namespace { // private test classes and data... + + const uint NUM_COUNTERS = 20; ///< number of independent counters to increment in parallel + const uint NUM_THREADS = 10; ///< number of threads trying to increment these counters + const uint MAX_PAUSE = 10000; ///< maximum delay implemented as empty counting loop + const uint MAX_SUM = 1000; ///< trigger when to finish incrementing + const uint MAX_INC = 10; ///< maximum increment on each step + + + + class Victim + { + long cnt_[NUM_COUNTERS]; + uint step_; ///< @note stored as instance variable + + void + pause () + { + //Lock guard (*this); // note recursive lock + for ( uint i=0, lim=(rand() % MAX_PAUSE); ijoin(); + } + + void + start () + { + thread_ = Glib::Thread::create(sigc::mem_fun(*this, &HavocThread::doIt), true); + ASSERT (thread_); + } + }; + + } // (End) test classes and data.... + + + + + + + + + + + /********************************************************************** + * @test create multiple threads, all concurrently trying to increment + * a number of counters with random steps and random pauses. Without + * locking, the likely result will be differing counters. + * But because the class Victim uses an object level monitor to + * guard the mutations, the state should remain consistent. + * + * @see multithread.hpp + */ + class MultithreadLocking_test : public Test + { + + virtual void run(Arg arg) + { + if (!Glib::thread_supported()) + Glib::thread_init(); + + REQUIRE (ourVictim.checkAllEqual()); + { + HavocThread threads[NUM_THREADS]; + for (uint i=0; i=" << MAX_SUM << "\n"; + ourVictim.report(); + } + } + + }; + + + + /** Register this test class... */ + LAUNCHER (MultithreadLocking_test, "unit common"); + + + + } // namespace test + +} // namespace lumiera From 93b57b3bc828b916faea02edb82a43ff994cf992 Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Sun, 14 Dec 2008 04:35:36 +0100 Subject: [PATCH 032/214] SCons: add glib-- and gthread-2.0 to the build environment of Lumiera core --- SConstruct | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/SConstruct b/SConstruct index 52493aa4b..e38511152 100644 --- a/SConstruct +++ b/SConstruct @@ -255,6 +255,9 @@ def configurePlatform(env): if not conf.CheckPkgConfig('glibmm-2.4', '2.16'): problems.append('Unable to configure Lib glib--, exiting.') + if not conf.CheckPkgConfig('gthread-2.0', '2.16'): + problems.append('Need gthread support lib for glib-- based thread handling.') + if not conf.CheckPkgConfig('cairomm-1.0', 0.6): problems.append('Unable to configure Cairo--, exiting.') @@ -312,6 +315,8 @@ def defineBuildTargets(env, artifacts): setup sub-environments with special build options if necessary. We use a custom function to declare a whole tree of srcfiles. """ + env.mergeConf(['glibmm-2.4','gthread-2.0']) + # use PCH to speed up building # env['GCH'] = ( env.PrecompiledHeader('$SRCDIR/pre.hpp') # + env.PrecompiledHeader('$SRCDIR/pre_a.hpp') From ee4c910ed410cf13a62befe670277a42ced4c26f Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Mon, 15 Dec 2008 03:13:14 +0100 Subject: [PATCH 033/214] qualify with volatile (fix) --- tests/common/multithread-locking-test.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/common/multithread-locking-test.cpp b/tests/common/multithread-locking-test.cpp index d03fe5c28..465929e55 100644 --- a/tests/common/multithread-locking-test.cpp +++ b/tests/common/multithread-locking-test.cpp @@ -56,8 +56,8 @@ namespace lib { class Victim { - long cnt_[NUM_COUNTERS]; - uint step_; ///< @note stored as instance variable + volatile long cnt_[NUM_COUNTERS]; + volatile uint step_; ///< @note stored as instance variable void pause () From d1e385f3f43beacff896d90434501267012ac3d1 Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Mon, 15 Dec 2008 04:14:15 +0100 Subject: [PATCH 034/214] rename class Thread into Concurrency it's not a thread abstraction, but a locking helper --- src/lib/Makefile.am | 2 +- src/lib/allocationcluster.cpp | 12 ++++++------ src/lib/allocationcluster.hpp | 6 +++--- src/lib/{multithread.hpp => concurrency.hpp} | 7 +++---- src/lib/singletonpolicies.hpp | 4 ++-- src/lib/visitordispatcher.hpp | 8 ++++---- src/proc/assetmanager.cpp | 6 +++--- src/proc/mobject/session/defsregistry.hpp | 6 +++--- tests/40components.tests | 10 +++++----- ...locking-test.cpp => concurrency-locking-test.cpp} | 10 +++++----- 10 files changed, 35 insertions(+), 36 deletions(-) rename src/lib/{multithread.hpp => concurrency.hpp} (93%) rename tests/common/{multithread-locking-test.cpp => concurrency-locking-test.cpp} (95%) diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am index 4608feedb..6460a0f88 100644 --- a/src/lib/Makefile.am +++ b/src/lib/Makefile.am @@ -68,7 +68,7 @@ noinst_HEADERS += \ $(liblumiera_la_srcdir)/visitor.hpp \ $(liblumiera_la_srcdir)/visitordispatcher.hpp \ $(liblumiera_la_srcdir)/visitorpolicies.hpp \ - $(liblumiera_la_srcdir)/multithread.hpp \ + $(liblumiera_la_srcdir)/concurrency.hpp \ $(liblumiera_la_srcdir)/p.hpp \ $(liblumiera_la_srcdir)/query.hpp \ $(liblumiera_la_srcdir)/singletonfactory.hpp \ diff --git a/src/lib/allocationcluster.cpp b/src/lib/allocationcluster.cpp index e30561952..20ae8ae0a 100644 --- a/src/lib/allocationcluster.cpp +++ b/src/lib/allocationcluster.cpp @@ -81,7 +81,7 @@ namespace lib { void AllocationCluster::MemoryManager::reset (TypeInfo info) { - Thread::Lock guard SIDEEFFECT; + Concurrency::Lock guard SIDEEFFECT; if (0 < mem_.size()) purge(); type_ = info; @@ -96,7 +96,7 @@ namespace lib { void AllocationCluster::MemoryManager::purge() { - Thread::Lock guard SIDEEFFECT; + Concurrency::Lock guard SIDEEFFECT; REQUIRE (type_.killIt, "we need a deleter function"); REQUIRE (0 < type_.allocSize, "allocation size unknown"); @@ -120,7 +120,7 @@ namespace lib { inline void* AllocationCluster::MemoryManager::allocate() { - Thread::Lock guard SIDEEFFECT; + Concurrency::Lock guard SIDEEFFECT; REQUIRE (0 < type_.allocSize); REQUIRE (top_ <= mem_.size()); @@ -140,7 +140,7 @@ namespace lib { inline void AllocationCluster::MemoryManager::commit (void* pendingAlloc) { - Thread::Lock guard SIDEEFFECT; + Concurrency::Lock guard SIDEEFFECT; REQUIRE (pendingAlloc); ASSERT (top_ < mem_.size()); @@ -175,7 +175,7 @@ namespace lib { { try { - Thread::Lock guard SIDEEFFECT + Concurrency::Lock guard SIDEEFFECT TRACE (memory, "shutting down AllocationCluster"); for (size_t i = typeHandlers_.size(); 0 < i; --i) @@ -214,7 +214,7 @@ namespace lib { ASSERT (0 < slot); { - Thread::Lock guard SIDEEFFECT; /////TODO: decide tradeoff: lock just the instance, or lock the AllocationCluster class? + Concurrency::Lock guard SIDEEFFECT; /////TODO: decide tradeoff: lock just the instance, or lock the AllocationCluster class? if (slot > typeHandlers_.size()) typeHandlers_.resize(slot); diff --git a/src/lib/allocationcluster.hpp b/src/lib/allocationcluster.hpp index 0e6a61a8d..ada15c501 100644 --- a/src/lib/allocationcluster.hpp +++ b/src/lib/allocationcluster.hpp @@ -51,8 +51,8 @@ #include #include -#include "lib/multithread.hpp" #include "include/error.hpp" +#include "lib/concurrency.hpp" #include "lib/scopedholder.hpp" #include "lib/scopedholdertransfer.hpp" @@ -60,7 +60,7 @@ namespace lib { using boost::scoped_ptr; - using lumiera::Thread; + using lumiera::Concurrency; /** * A pile of objects sharing common allocation and lifecycle. @@ -223,7 +223,7 @@ namespace lib { static TypeInfo setup() { - Thread::Lock guard SIDEEFFECT; + Concurrency::Lock guard SIDEEFFECT; if (!id_) id_= ++maxTypeIDs; diff --git a/src/lib/multithread.hpp b/src/lib/concurrency.hpp similarity index 93% rename from src/lib/multithread.hpp rename to src/lib/concurrency.hpp index 2d3b4b31f..f13f44711 100644 --- a/src/lib/multithread.hpp +++ b/src/lib/concurrency.hpp @@ -1,5 +1,5 @@ /* - MULTITHREAD.hpp - generic interface for multithreading primitives + CONCURRENCY.hpp - generic interface for multithreading primitives Copyright (C) Lumiera.org 2008, Christian Thaeter @@ -30,8 +30,7 @@ #include "lib/util.hpp" -namespace lumiera - { +namespace lumiera { /** * Interface/Policy for managing parallelism issues. @@ -40,7 +39,7 @@ namespace lumiera * * @todo actually implement this policy using the Lumiera databackend. */ - struct Thread + struct Concurrency { template class Lock diff --git a/src/lib/singletonpolicies.hpp b/src/lib/singletonpolicies.hpp index 572467264..25c174a58 100644 --- a/src/lib/singletonpolicies.hpp +++ b/src/lib/singletonpolicies.hpp @@ -34,7 +34,7 @@ This code is heavily inspired by #ifndef LUMIERA_SINGLETONPOLICIES_H #define LUMIERA_SINGLETONPOLICIES_H -#include "lib/multithread.hpp" +#include "lib/concurrency.hpp" #include "include/error.hpp" #include @@ -139,7 +139,7 @@ namespace lumiera struct Multithreaded { typedef volatile S VolatileType; - typedef lumiera::Thread::Lock Lock; + typedef lumiera::Concurrency::Lock Lock; }; diff --git a/src/lib/visitordispatcher.hpp b/src/lib/visitordispatcher.hpp index 857047aa5..5598b243c 100644 --- a/src/lib/visitordispatcher.hpp +++ b/src/lib/visitordispatcher.hpp @@ -26,9 +26,9 @@ #define LUMIERA_VISITORDISPATCHER_H #include "include/error.hpp" -#include "lib/util.hpp" +#include "lib/concurrency.hpp" #include "lib/singleton.hpp" -#include "lib/multithread.hpp" +#include "lib/util.hpp" #include @@ -62,7 +62,7 @@ namespace lumiera static void generateID (size_t& id) { - Thread::Lock guard SIDEEFFECT; + Concurrency::Lock guard SIDEEFFECT; if (!id) id = ++lastRegisteredID; } @@ -138,7 +138,7 @@ namespace lumiera void accomodate (size_t index) { - Thread::Lock guard SIDEEFFECT; + Concurrency::Lock guard SIDEEFFECT; if (index > table_.size()) table_.resize (index); // performance bottleneck?? TODO: measure the real impact! } diff --git a/src/proc/assetmanager.cpp b/src/proc/assetmanager.cpp index 3c17421a9..9251ceaab 100644 --- a/src/proc/assetmanager.cpp +++ b/src/proc/assetmanager.cpp @@ -24,7 +24,7 @@ #include "proc/assetmanager.hpp" #include "proc/asset/db.hpp" -#include "lib/multithread.hpp" +#include "lib/concurrency.hpp" #include "lib/util.hpp" #include @@ -39,7 +39,7 @@ using boost::bind; using util::for_each; using lumiera::Singleton; -using lumiera::Thread; +using lumiera::Concurrency; namespace asset @@ -116,7 +116,7 @@ namespace asset TODO ("check validity of Ident Category"); ID asset_id (getID (idi)); - Thread::Lock guard SIDEEFFECT; + Concurrency::Lock guard SIDEEFFECT; TODO ("handle duplicate Registrations"); P smart_ptr (obj, &destroy); diff --git a/src/proc/mobject/session/defsregistry.hpp b/src/proc/mobject/session/defsregistry.hpp index da79f40fa..89054de66 100644 --- a/src/proc/mobject/session/defsregistry.hpp +++ b/src/proc/mobject/session/defsregistry.hpp @@ -40,7 +40,7 @@ #define MOBJECT_SESSION_DEFSREGISTRY_H -#include "lib/multithread.hpp" +#include "lib/concurrency.hpp" #include "lib/query.hpp" #include "lib/util.hpp" #include "lib/p.hpp" @@ -59,7 +59,7 @@ namespace mobject { using lumiera::P; using lumiera::Query; - using lumiera::Thread; + using lumiera::Concurrency; using std::tr1::weak_ptr; using std::string; @@ -163,7 +163,7 @@ namespace mobject static void createSlot (Table& table) { - Thread::Lock guard SIDEEFFECT; + Concurrency::Lock guard SIDEEFFECT; if (!index) index = ++maxSlots; if (index > table.size()) diff --git a/tests/40components.tests b/tests/40components.tests index c73e24eb1..c1bf07b0c 100644 --- a/tests/40components.tests +++ b/tests/40components.tests @@ -158,6 +158,11 @@ return: 0 END +PLANNED "Multithread Locking by Monitor" ConcurrencyLocking_test < [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, ] out: removed 0 ---> [ 1, 2, 3, 4, 5, 6, 7, 8, 9, ] diff --git a/tests/common/multithread-locking-test.cpp b/tests/common/concurrency-locking-test.cpp similarity index 95% rename from tests/common/multithread-locking-test.cpp rename to tests/common/concurrency-locking-test.cpp index 465929e55..c55aac0bf 100644 --- a/tests/common/multithread-locking-test.cpp +++ b/tests/common/concurrency-locking-test.cpp @@ -1,5 +1,5 @@ /* - MultithreadLocking(Test) - check the monitor object based locking + ConcurrencyLocking(Test) - check the monitor object based locking Copyright (C) Lumiera.org 2008, Hermann Vosseler @@ -25,7 +25,7 @@ //#include "common/util.hpp" #include "common/error.hpp" -#include "common/multithread.hpp" +#include "common/concurrency.hpp" #include @@ -171,9 +171,9 @@ namespace lib { * But because the class Victim uses an object level monitor to * guard the mutations, the state should remain consistent. * - * @see multithread.hpp + * @see concurrency.hpp */ - class MultithreadLocking_test : public Test + class ConcurrencyLocking_test : public Test { virtual void run(Arg arg) @@ -202,7 +202,7 @@ namespace lib { /** Register this test class... */ - LAUNCHER (MultithreadLocking_test, "unit common"); + LAUNCHER (ConcurrencyLocking_test, "unit common"); From 112cd475b7bc2cfbc1c3146097f687e88f339657 Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Mon, 15 Dec 2008 05:05:12 +0100 Subject: [PATCH 035/214] WIP draft the basic pattern --- src/lib/concurrency.hpp | 61 ++++++++++++++++++++++++++++++++++------- 1 file changed, 51 insertions(+), 10 deletions(-) diff --git a/src/lib/concurrency.hpp b/src/lib/concurrency.hpp index f13f44711..87ebfa45b 100644 --- a/src/lib/concurrency.hpp +++ b/src/lib/concurrency.hpp @@ -1,5 +1,5 @@ /* - CONCURRENCY.hpp - generic interface for multithreading primitives + CONCURRENCY.hpp - generic helper for object based locking and synchronisation Copyright (C) Lumiera.org 2008, Christian Thaeter @@ -21,10 +21,21 @@ */ +/** @file concurrency.hpp + ** Collection of helpers and wrappers to support dealing with concurrency issues. + ** Actually, everything is implemented either by the Lumiera backend, or directly + ** by pthread. The purpose is to support and automate the most common use cases + ** in object oriented style. + ** + ** @see mutex.h + ** @see concurrency-locking-test.cpp + ** @see asset::AssetManager::reg() usage example + ** @see subsystemrunner.hpp usage example + */ -#ifndef LUMIERA_MULTITHREAD_H -#define LUMIERA_MULTITHREAD_H +#ifndef LUMIERA_CONCURRENCY_H +#define LUMIERA_CONCURRENCY_H #include "include/nobugcfg.h" #include "lib/util.hpp" @@ -33,24 +44,54 @@ namespace lumiera { /** - * Interface/Policy for managing parallelism issues. - * Basically everything is forwarded to the corresponding backend functions, - * because managing threads and locking belongs to the Lumiera backend layer. + * Facility for monitor object based locking. + * To be attached either on a per class base or per object base. + * Typically, the client class will inherit from this template (but it + * is possible to use it stand-alone, if inheriting isn't an option). + * The interface for clients to access the functionality is the embedded + * Lock template, which should be instantiated as an automatic variable + * within the scope to be protected. * - * @todo actually implement this policy using the Lumiera databackend. + * @todo actually implement this facility using the Lumiera backend. */ struct Concurrency { + struct Monitor + { + void acquireLock() { TODO ("acquire Thread Lock"); } + void releaseLock() { TODO ("release Thread Lock"); } + }; + + template + static Monitor& getMonitor(X* forThis); + template class Lock { + Monitor& mon_; public: - Lock() { TODO ("aquire Thread Lock for Class"); } - Lock(X*) { TODO ("aquire Thread Lock for Instance"); } - ~Lock() { TODO ("release Thread Lock"); } + Lock(X* it=0) + : mon_(getMonitor (it)) + { + mon_.acquireLock(); + } + + ~Lock() + { + mon_.releaseLock(); + } }; }; + + + template + Concurrency::Monitor& + Concurrency::getMonitor(X* forThis) + { + UNIMPLEMENTED ("get moni"); + } + } // namespace lumiera #endif From 2512f04f3f874d7549a21db1c470c7492aa4f243 Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Mon, 15 Dec 2008 05:20:30 +0100 Subject: [PATCH 036/214] WIP yet another namespace change. Now refer it from the test --- src/lib/allocationcluster.hpp | 1 - src/lib/concurrency.hpp | 6 +++--- src/lib/singletonpolicies.hpp | 2 +- src/lib/visitordispatcher.hpp | 8 ++++---- src/proc/assetmanager.cpp | 2 +- src/proc/mobject/session/defsregistry.hpp | 9 ++++----- tests/common/concurrency-locking-test.cpp | 7 ++++--- 7 files changed, 17 insertions(+), 18 deletions(-) diff --git a/src/lib/allocationcluster.hpp b/src/lib/allocationcluster.hpp index ada15c501..0e1e85fdd 100644 --- a/src/lib/allocationcluster.hpp +++ b/src/lib/allocationcluster.hpp @@ -60,7 +60,6 @@ namespace lib { using boost::scoped_ptr; - using lumiera::Concurrency; /** * A pile of objects sharing common allocation and lifecycle. diff --git a/src/lib/concurrency.hpp b/src/lib/concurrency.hpp index 87ebfa45b..e00f1bd5d 100644 --- a/src/lib/concurrency.hpp +++ b/src/lib/concurrency.hpp @@ -34,14 +34,14 @@ */ -#ifndef LUMIERA_CONCURRENCY_H -#define LUMIERA_CONCURRENCY_H +#ifndef LIB_CONCURRENCY_H +#define LIB_CONCURRENCY_H #include "include/nobugcfg.h" #include "lib/util.hpp" -namespace lumiera { +namespace lib { /** * Facility for monitor object based locking. diff --git a/src/lib/singletonpolicies.hpp b/src/lib/singletonpolicies.hpp index 25c174a58..e00be62b6 100644 --- a/src/lib/singletonpolicies.hpp +++ b/src/lib/singletonpolicies.hpp @@ -139,7 +139,7 @@ namespace lumiera struct Multithreaded { typedef volatile S VolatileType; - typedef lumiera::Concurrency::Lock Lock; + typedef lib::Concurrency::Lock Lock; }; diff --git a/src/lib/visitordispatcher.hpp b/src/lib/visitordispatcher.hpp index 5598b243c..46db635b0 100644 --- a/src/lib/visitordispatcher.hpp +++ b/src/lib/visitordispatcher.hpp @@ -33,10 +33,10 @@ #include -namespace lumiera - { - namespace visitor - { +namespace lumiera { + namespace visitor { + + using lib::Concurrency; template class Tag; diff --git a/src/proc/assetmanager.cpp b/src/proc/assetmanager.cpp index 9251ceaab..7c4b6da06 100644 --- a/src/proc/assetmanager.cpp +++ b/src/proc/assetmanager.cpp @@ -39,7 +39,7 @@ using boost::bind; using util::for_each; using lumiera::Singleton; -using lumiera::Concurrency; +using lib::Concurrency; namespace asset diff --git a/src/proc/mobject/session/defsregistry.hpp b/src/proc/mobject/session/defsregistry.hpp index 89054de66..3920ed143 100644 --- a/src/proc/mobject/session/defsregistry.hpp +++ b/src/proc/mobject/session/defsregistry.hpp @@ -53,13 +53,12 @@ #include -namespace mobject - { - namespace session - { +namespace mobject { + namespace session { + using lumiera::P; using lumiera::Query; - using lumiera::Concurrency; + using lib::Concurrency; using std::tr1::weak_ptr; using std::string; diff --git a/tests/common/concurrency-locking-test.cpp b/tests/common/concurrency-locking-test.cpp index c55aac0bf..7729e4dc4 100644 --- a/tests/common/concurrency-locking-test.cpp +++ b/tests/common/concurrency-locking-test.cpp @@ -55,6 +55,7 @@ namespace lib { class Victim + : Concurrency { volatile long cnt_[NUM_COUNTERS]; volatile uint step_; ///< @note stored as instance variable @@ -62,7 +63,7 @@ namespace lib { void pause () { - //Lock guard (*this); // note recursive lock + Lock guard (this); // note recursive lock for ( uint i=0, lim=(rand() % MAX_PAUSE); i guard (this); step_ = newStep; incrementAll(); } @@ -95,7 +96,7 @@ namespace lib { bool belowLimit () { - //Lock guard (*this); + Lock guard (this); return cnt_[0] < MAX_SUM; } From c4df935113c33f00394065c833f3e65d3a9cae36 Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Mon, 15 Dec 2008 06:18:38 +0100 Subject: [PATCH 037/214] add draft impl for Monitor storage; dummy impl running todo: actually do any locking, improve handling of the forThis parameter --- src/lib/concurrency.hpp | 50 +++++++++++++++++++---- tests/common/concurrency-locking-test.cpp | 3 +- 2 files changed, 45 insertions(+), 8 deletions(-) diff --git a/src/lib/concurrency.hpp b/src/lib/concurrency.hpp index e00f1bd5d..369afa01a 100644 --- a/src/lib/concurrency.hpp +++ b/src/lib/concurrency.hpp @@ -40,8 +40,15 @@ #include "include/nobugcfg.h" #include "lib/util.hpp" +#include + +#include ///////////////////////////TODO +using std::cerr; + namespace lib { + + using boost::scoped_ptr; /** * Facility for monitor object based locking. @@ -58,20 +65,38 @@ namespace lib { { struct Monitor { - void acquireLock() { TODO ("acquire Thread Lock"); } - void releaseLock() { TODO ("release Thread Lock"); } + Monitor() { TODO ("maybe create mutex struct here?"); } + ~Monitor() { TODO ("destroy mutex, assert it isn't locked!"); } /////TODO: Probably need to unlock it silently in case of a class-level monitor? + + void acquireLock() { cerr << "acquire Thread Lock\n"; } + void releaseLock() { cerr << "release Thread Lock\n"; } }; + Monitor objectMonitor_; + + /////////////////////////////////////////////////////////////////////////TODO: any better idea for where to put the template parameter? so we can get rid of it for the typical usage scenario? + /////////////////////////////////////////////////////////////////////////TODO: better solution for the storage? Implement the per-this locking without subclassing! + /////////////////////////////////////////////////////////////////////////TODO: factor out the recursive/non-recursive mutex case as policy... + template - static Monitor& getMonitor(X* forThis); + static inline Monitor& getMonitor(); + + static inline Monitor& getMonitor(Concurrency* forThis); + template class Lock { Monitor& mon_; public: - Lock(X* it=0) - : mon_(getMonitor (it)) + Lock(X* it) + : mon_(getMonitor(it)) + { + mon_.acquireLock(); + } + + Lock() + : mon_(getMonitor()) { mon_.acquireLock(); } @@ -85,11 +110,22 @@ namespace lib { + Concurrency::Monitor& + Concurrency::getMonitor(Concurrency* forThis) + { + REQUIRE (forThis); + return forThis->objectMonitor_; + } + template Concurrency::Monitor& - Concurrency::getMonitor(X* forThis) + Concurrency::getMonitor() { - UNIMPLEMENTED ("get moni"); + //TODO: guard this by a Mutex? consider double checked locking? (but then class Monitor needs to be volatile, thus is it worth the effort?) + + static scoped_ptr classMonitor_ (0); + if (!classMonitor_) classMonitor_.reset (new Monitor ()); + return *classMonitor_; } diff --git a/tests/common/concurrency-locking-test.cpp b/tests/common/concurrency-locking-test.cpp index 7729e4dc4..e3b0bbbe6 100644 --- a/tests/common/concurrency-locking-test.cpp +++ b/tests/common/concurrency-locking-test.cpp @@ -55,7 +55,7 @@ namespace lib { class Victim - : Concurrency + : public Concurrency { volatile long cnt_[NUM_COUNTERS]; volatile uint step_; ///< @note stored as instance variable @@ -64,6 +64,7 @@ namespace lib { pause () { Lock guard (this); // note recursive lock + for ( uint i=0, lim=(rand() % MAX_PAUSE); i Date: Tue, 16 Dec 2008 05:19:31 +0100 Subject: [PATCH 038/214] better invocation, get rid of the template parameter --- src/lib/allocationcluster.cpp | 12 ++++++------ src/lib/allocationcluster.hpp | 2 +- src/lib/concurrency.hpp | 18 ++++++++++++------ src/lib/singletonpolicies.hpp | 2 +- src/lib/visitordispatcher.hpp | 4 ++-- src/proc/assetmanager.cpp | 2 +- src/proc/mobject/session/defsregistry.hpp | 2 +- tests/common/concurrency-locking-test.cpp | 6 +++--- 8 files changed, 27 insertions(+), 21 deletions(-) diff --git a/src/lib/allocationcluster.cpp b/src/lib/allocationcluster.cpp index 20ae8ae0a..06982df51 100644 --- a/src/lib/allocationcluster.cpp +++ b/src/lib/allocationcluster.cpp @@ -81,7 +81,7 @@ namespace lib { void AllocationCluster::MemoryManager::reset (TypeInfo info) { - Concurrency::Lock guard SIDEEFFECT; + Concurrency::ClassLock guard(); if (0 < mem_.size()) purge(); type_ = info; @@ -96,7 +96,7 @@ namespace lib { void AllocationCluster::MemoryManager::purge() { - Concurrency::Lock guard SIDEEFFECT; + Concurrency::ClassLock guard(); REQUIRE (type_.killIt, "we need a deleter function"); REQUIRE (0 < type_.allocSize, "allocation size unknown"); @@ -120,7 +120,7 @@ namespace lib { inline void* AllocationCluster::MemoryManager::allocate() { - Concurrency::Lock guard SIDEEFFECT; + Concurrency::ClassLock guard(); REQUIRE (0 < type_.allocSize); REQUIRE (top_ <= mem_.size()); @@ -140,7 +140,7 @@ namespace lib { inline void AllocationCluster::MemoryManager::commit (void* pendingAlloc) { - Concurrency::Lock guard SIDEEFFECT; + Concurrency::ClassLock guard(); REQUIRE (pendingAlloc); ASSERT (top_ < mem_.size()); @@ -175,7 +175,7 @@ namespace lib { { try { - Concurrency::Lock guard SIDEEFFECT + Concurrency::ClassLock guard(); TRACE (memory, "shutting down AllocationCluster"); for (size_t i = typeHandlers_.size(); 0 < i; --i) @@ -214,7 +214,7 @@ namespace lib { ASSERT (0 < slot); { - Concurrency::Lock guard SIDEEFFECT; /////TODO: decide tradeoff: lock just the instance, or lock the AllocationCluster class? + Concurrency::ClassLock guard(); /////TODO: decide tradeoff: lock just the instance, or lock the AllocationCluster class? if (slot > typeHandlers_.size()) typeHandlers_.resize(slot); diff --git a/src/lib/allocationcluster.hpp b/src/lib/allocationcluster.hpp index 0e1e85fdd..dd7ce8959 100644 --- a/src/lib/allocationcluster.hpp +++ b/src/lib/allocationcluster.hpp @@ -222,7 +222,7 @@ namespace lib { static TypeInfo setup() { - Concurrency::Lock guard SIDEEFFECT; + Concurrency::ClassLock guard(); if (!id_) id_= ++maxTypeIDs; diff --git a/src/lib/concurrency.hpp b/src/lib/concurrency.hpp index 369afa01a..fc40a4edf 100644 --- a/src/lib/concurrency.hpp +++ b/src/lib/concurrency.hpp @@ -74,7 +74,6 @@ namespace lib { Monitor objectMonitor_; - /////////////////////////////////////////////////////////////////////////TODO: any better idea for where to put the template parameter? so we can get rid of it for the typical usage scenario? /////////////////////////////////////////////////////////////////////////TODO: better solution for the storage? Implement the per-this locking without subclassing! /////////////////////////////////////////////////////////////////////////TODO: factor out the recursive/non-recursive mutex case as policy... @@ -84,19 +83,17 @@ namespace lib { static inline Monitor& getMonitor(Concurrency* forThis); - template class Lock { Monitor& mon_; public: - Lock(X* it) - : mon_(getMonitor(it)) + template + Lock(X* it) : mon_(getMonitor(it)) { mon_.acquireLock(); } - Lock() - : mon_(getMonitor()) + Lock(Monitor& m) : mon_(m) { mon_.acquireLock(); } @@ -106,8 +103,17 @@ namespace lib { mon_.releaseLock(); } }; + + template + struct ClassLock : Lock + { + ClassLock() : Lock (getMonitor()) {} + }; + }; + + Concurrency::Monitor& diff --git a/src/lib/singletonpolicies.hpp b/src/lib/singletonpolicies.hpp index e00be62b6..afbb87253 100644 --- a/src/lib/singletonpolicies.hpp +++ b/src/lib/singletonpolicies.hpp @@ -139,7 +139,7 @@ namespace lumiera struct Multithreaded { typedef volatile S VolatileType; - typedef lib::Concurrency::Lock Lock; + typedef lib::Concurrency::ClassLock Lock; }; diff --git a/src/lib/visitordispatcher.hpp b/src/lib/visitordispatcher.hpp index 46db635b0..de56445b9 100644 --- a/src/lib/visitordispatcher.hpp +++ b/src/lib/visitordispatcher.hpp @@ -62,7 +62,7 @@ namespace lumiera { static void generateID (size_t& id) { - Concurrency::Lock guard SIDEEFFECT; + Concurrency::ClassLock guard(); if (!id) id = ++lastRegisteredID; } @@ -138,7 +138,7 @@ namespace lumiera { void accomodate (size_t index) { - Concurrency::Lock guard SIDEEFFECT; + Concurrency::ClassLock guard(); if (index > table_.size()) table_.resize (index); // performance bottleneck?? TODO: measure the real impact! } diff --git a/src/proc/assetmanager.cpp b/src/proc/assetmanager.cpp index 7c4b6da06..fb2623153 100644 --- a/src/proc/assetmanager.cpp +++ b/src/proc/assetmanager.cpp @@ -116,7 +116,7 @@ namespace asset TODO ("check validity of Ident Category"); ID asset_id (getID (idi)); - Concurrency::Lock guard SIDEEFFECT; + Concurrency::ClassLock guard(); TODO ("handle duplicate Registrations"); P smart_ptr (obj, &destroy); diff --git a/src/proc/mobject/session/defsregistry.hpp b/src/proc/mobject/session/defsregistry.hpp index 3920ed143..8a3fcdfd5 100644 --- a/src/proc/mobject/session/defsregistry.hpp +++ b/src/proc/mobject/session/defsregistry.hpp @@ -162,7 +162,7 @@ namespace mobject { static void createSlot (Table& table) { - Concurrency::Lock guard SIDEEFFECT; + Concurrency::ClassLock guard(); if (!index) index = ++maxSlots; if (index > table.size()) diff --git a/tests/common/concurrency-locking-test.cpp b/tests/common/concurrency-locking-test.cpp index e3b0bbbe6..2bc7065b1 100644 --- a/tests/common/concurrency-locking-test.cpp +++ b/tests/common/concurrency-locking-test.cpp @@ -63,7 +63,7 @@ namespace lib { void pause () { - Lock guard (this); // note recursive lock + Lock guard (this); // note recursive lock for ( uint i=0, lim=(rand() % MAX_PAUSE); i guard (this); + Lock guard (this); step_ = newStep; incrementAll(); } @@ -97,7 +97,7 @@ namespace lib { bool belowLimit () { - Lock guard (this); + Lock guard (this); return cnt_[0] < MAX_SUM; } From 6031ac24659ad4c7c0d64ded0f20a8143e9c5705 Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Sat, 20 Dec 2008 06:33:36 +0100 Subject: [PATCH 039/214] FIX after rebase --- src/common/subsystemrunner.hpp | 2 +- tests/{common => lib}/concurrency-locking-test.cpp | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) rename tests/{common => lib}/concurrency-locking-test.cpp (98%) diff --git a/src/common/subsystemrunner.hpp b/src/common/subsystemrunner.hpp index 840e35728..ca81d1686 100644 --- a/src/common/subsystemrunner.hpp +++ b/src/common/subsystemrunner.hpp @@ -27,7 +27,7 @@ #include "include/error.hpp" #include "lib/util.hpp" #include "common/subsys.hpp" -#include "lib/multithread.hpp" +#include "lib/concurrency.hpp" #include #include diff --git a/tests/common/concurrency-locking-test.cpp b/tests/lib/concurrency-locking-test.cpp similarity index 98% rename from tests/common/concurrency-locking-test.cpp rename to tests/lib/concurrency-locking-test.cpp index 2bc7065b1..86087e1c5 100644 --- a/tests/common/concurrency-locking-test.cpp +++ b/tests/lib/concurrency-locking-test.cpp @@ -21,11 +21,11 @@ * *****************************************************/ -#include "common/test/run.hpp" +#include "lib/test/run.hpp" //#include "common/util.hpp" -#include "common/error.hpp" +#include "include/error.hpp" -#include "common/concurrency.hpp" +#include "lib/concurrency.hpp" #include From 79b1515f71adb71cef96889b7528530ad1bc8e1e Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Sun, 21 Dec 2008 20:48:10 +0100 Subject: [PATCH 040/214] typo --- src/proc/assetmanager.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/proc/assetmanager.cpp b/src/proc/assetmanager.cpp index fb2623153..24b39dfbc 100644 --- a/src/proc/assetmanager.cpp +++ b/src/proc/assetmanager.cpp @@ -143,11 +143,11 @@ namespace asset throw UnknownID (id); } - /** convienience shortcut for fetching the registered smart-ptr + /** Convenience shortcut for fetching the registered smart-ptr * which is in charge of the given asset instance. By querying * directly asset.id (of type ID), the call to registry.get() * can bypass the dynamic cast, because the type of the asset - * is explicitely given by type KIND. + * is explicitly given by type KIND. */ template P @@ -197,7 +197,7 @@ namespace asset /** * remove the given asset from the internal DB - * together with all its dependants + * together with all its dependents */ void AssetManager::remove (IDA id) From 9240da002fc486bffe1314d9d98f056184417d47 Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Mon, 22 Dec 2008 04:50:27 +0100 Subject: [PATCH 041/214] WIP --- src/lib/concurrency.hpp | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/src/lib/concurrency.hpp b/src/lib/concurrency.hpp index fc40a4edf..d03a4edb1 100644 --- a/src/lib/concurrency.hpp +++ b/src/lib/concurrency.hpp @@ -40,6 +40,11 @@ #include "include/nobugcfg.h" #include "lib/util.hpp" +extern "C" { +#include "lib/mutex.h" +#include "lib/condition.h" +} + #include #include ///////////////////////////TODO @@ -65,8 +70,16 @@ namespace lib { { struct Monitor { - Monitor() { TODO ("maybe create mutex struct here?"); } - ~Monitor() { TODO ("destroy mutex, assert it isn't locked!"); } /////TODO: Probably need to unlock it silently in case of a class-level monitor? + lumiera_mutex mtx_; + + Monitor() + { + lumiera_recmutex_init (&mtx_, "Monitor object", &NOBUG_FLAG (memory)); + } + ~Monitor() + { + lumiera_mutex_destroy (&mtx_, &NOBUG_FLAG (memory)); + } void acquireLock() { cerr << "acquire Thread Lock\n"; } void releaseLock() { cerr << "release Thread Lock\n"; } @@ -74,7 +87,6 @@ namespace lib { Monitor objectMonitor_; - /////////////////////////////////////////////////////////////////////////TODO: better solution for the storage? Implement the per-this locking without subclassing! /////////////////////////////////////////////////////////////////////////TODO: factor out the recursive/non-recursive mutex case as policy... template @@ -127,7 +139,10 @@ namespace lib { Concurrency::Monitor& Concurrency::getMonitor() { - //TODO: guard this by a Mutex? consider double checked locking? (but then class Monitor needs to be volatile, thus is it worth the effort?) + //TODO: a rather obscure race condition is hidden here: + //TODO: depending on the build order, the dtor of this static variable may be called, while another thread is still holding an ClassLock. + //TODO: An possible solution would be to use an shared_ptr to the Monitor in case of a ClassLock and to protect access with another Mutex. + //TODO. But I am really questioning if we can't ignore this case and state: "don't hold a ClassLock when your code maybe still running in shutdown phase!" static scoped_ptr classMonitor_ (0); if (!classMonitor_) classMonitor_.reset (new Monitor ()); From 67e95884d5096a51fec4e0a8e8e6406bf445a8a2 Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Mon, 22 Dec 2008 07:23:48 +0100 Subject: [PATCH 042/214] preliminary implementation using pthread primitives. Locking test pass. --- src/include/nobugcfg.h | 2 ++ src/lib/concurrency.hpp | 50 ++++++++++++++++++-------- tests/lib/concurrency-locking-test.cpp | 10 ++---- 3 files changed, 40 insertions(+), 22 deletions(-) diff --git a/src/include/nobugcfg.h b/src/include/nobugcfg.h index cfcedd6b7..d8ea8ab26 100644 --- a/src/include/nobugcfg.h +++ b/src/include/nobugcfg.h @@ -88,6 +88,7 @@ namespace lumiera { NOBUG_DECLARE_FLAG (render); ///< logging channel focusing on the render engine's workings NOBUG_DECLARE_FLAG (config); ///< logging channel covering application and session configuration NOBUG_DECLARE_FLAG (memory); ///< logging channel covering memory management issues + NOBUG_DECLARE_FLAG (sync); ///< especially for tracing synchronisation NOBUG_DECLARE_FLAG (test); @@ -109,6 +110,7 @@ namespace lumiera { NOBUG_CPP_DEFINE_FLAG_PARENT (operate, lumiera); NOBUG_CPP_DEFINE_FLAG_PARENT_LIMIT (render, lumiera, LOG_WARNING); NOBUG_CPP_DEFINE_FLAG_PARENT_LIMIT (memory, lumiera, LOG_WARNING); + NOBUG_CPP_DEFINE_FLAG_PARENT_LIMIT (sync, memory, LOG_WARNING); NOBUG_CPP_DEFINE_FLAG_PARENT_LIMIT (test, all, LOG_ERR); diff --git a/src/lib/concurrency.hpp b/src/lib/concurrency.hpp index d03a4edb1..d54952988 100644 --- a/src/lib/concurrency.hpp +++ b/src/lib/concurrency.hpp @@ -47,14 +47,43 @@ extern "C" { #include -#include ///////////////////////////TODO -using std::cerr; namespace lib { using boost::scoped_ptr; + + + namespace sync { // Helpers for Monitor based synchronisation + class RecMutex + { + lumiera_mutex mtx_; + + public: + RecMutex() { lumiera_recmutex_init (&mtx_, "Obj.Monitor RecMutex", &NOBUG_FLAG (sync)); } + ~RecMutex() { lumiera_mutex_destroy (&mtx_, &NOBUG_FLAG (sync)); } + + void acquire() + { + TODO ("Record we may block on mutex"); + + if (pthread_mutex_lock (&mtx_.mutex)) + throw lumiera::error::State("Mutex acquire failed."); ///////TODO capture the error-code + + TODO ("Record we successfully acquired the mutex"); + } + void release() + { + TODO ("Record we are releasing the mutex"); + pthread_mutex_unlock (&mtx_.mutex); + } + }; + + } // namespace sync + + + /** * Facility for monitor object based locking. * To be attached either on a per class base or per object base. @@ -70,19 +99,12 @@ namespace lib { { struct Monitor { - lumiera_mutex mtx_; + sync::RecMutex mtx_; + Monitor() {} + ~Monitor() {} - Monitor() - { - lumiera_recmutex_init (&mtx_, "Monitor object", &NOBUG_FLAG (memory)); - } - ~Monitor() - { - lumiera_mutex_destroy (&mtx_, &NOBUG_FLAG (memory)); - } - - void acquireLock() { cerr << "acquire Thread Lock\n"; } - void releaseLock() { cerr << "release Thread Lock\n"; } + void acquireLock() { mtx_.acquire(); } + void releaseLock() { mtx_.release(); } }; Monitor objectMonitor_; diff --git a/tests/lib/concurrency-locking-test.cpp b/tests/lib/concurrency-locking-test.cpp index 86087e1c5..32f1eb744 100644 --- a/tests/lib/concurrency-locking-test.cpp +++ b/tests/lib/concurrency-locking-test.cpp @@ -22,21 +22,14 @@ #include "lib/test/run.hpp" -//#include "common/util.hpp" #include "include/error.hpp" #include "lib/concurrency.hpp" #include -//#include -//#include #include -//using boost::lexical_cast; -//using boost::format; -//using util::isnil; -//using std::string; using std::cout; using test::Test; @@ -178,7 +171,8 @@ namespace lib { class ConcurrencyLocking_test : public Test { - virtual void run(Arg arg) + virtual void + run (Arg) { if (!Glib::thread_supported()) Glib::thread_init(); From 125db978ba6012cd9fbf57398d971549f1f1b180 Mon Sep 17 00:00:00 2001 From: Joel Holdsworth Date: Mon, 22 Dec 2008 11:36:46 +0000 Subject: [PATCH 043/214] WIP: Experimenting with track headers --- src/gui/widgets/timeline/timeline-track.cpp | 33 ++++++++++++++++----- src/gui/widgets/timeline/timeline-track.hpp | 7 +++++ 2 files changed, 32 insertions(+), 8 deletions(-) diff --git a/src/gui/widgets/timeline/timeline-track.cpp b/src/gui/widgets/timeline/timeline-track.cpp index 05f49b523..828598d4a 100644 --- a/src/gui/widgets/timeline/timeline-track.cpp +++ b/src/gui/widgets/timeline/timeline-track.cpp @@ -29,6 +29,7 @@ using namespace boost; using namespace Gtk; +using namespace sigc; namespace gui { namespace widgets { @@ -37,9 +38,14 @@ namespace timeline { Track::Track(TimelineWidget &timeline_widget) : timelineWidget(timeline_widget), expanded(true), + titleMenuButton("4HelloHelloHello"), enableButton(Gtk::StockID("track_enabled")), lockButton(Gtk::StockID("track_unlocked")) -{ +{ + titleMenuButton.set_relief(RELIEF_HALF); + titleMenuButton.signal_pressed().connect( + mem_fun(this, &Track::on_title_menu_button) ); + buttonBar.append(enableButton); buttonBar.append(lockButton); @@ -55,16 +61,20 @@ Track::Track(TimelineWidget &timeline_widget) : (GtkIconSize)(int)WindowManager::MenuIconSize); #endif - headerWidget.pack_start(titleBox, PACK_SHRINK); + headerWidget.pack_start(titleMenuButton, PACK_SHRINK); headerWidget.pack_start(buttonBar, PACK_SHRINK); + // Setup the title menu + Menu::MenuList& title_list = titleMenu.items(); + title_list.push_back( Menu_Helpers::MenuElem(_("_Name..."), + mem_fun(this, &Track::on_remove_track) ) ); + // Setup the context menu - Menu::MenuList& menu_list = contextMenu.items(); - menu_list.push_back( Menu_Helpers::MenuElem(_("_Add Track"), - sigc::mem_fun(timelineWidget, - &TimelineWidget::on_add_track_command) ) ); - menu_list.push_back( Menu_Helpers::MenuElem(_("_Remove Track"), - sigc::mem_fun(this, &Track::on_remove_track) ) ); + Menu::MenuList& context_list = contextMenu.items(); + context_list.push_back( Menu_Helpers::MenuElem(_("_Add Track"), + mem_fun(timelineWidget, &TimelineWidget::on_add_track_command) ) ); + context_list.push_back( Menu_Helpers::MenuElem(_("_Remove Track"), + mem_fun(this, &Track::on_remove_track) ) ); } Gtk::Widget& @@ -97,6 +107,13 @@ Track::show_header_context_menu(guint button, guint32 time) contextMenu.popup(button, time); } +void +Track::on_title_menu_button() +{ + g_message("Hello"); + titleMenu.popup(0, gtk_get_current_event_time()); +} + void Track::on_remove_track() { diff --git a/src/gui/widgets/timeline/timeline-track.hpp b/src/gui/widgets/timeline/timeline-track.hpp index d5ad70538..0fdd87884 100644 --- a/src/gui/widgets/timeline/timeline-track.hpp +++ b/src/gui/widgets/timeline/timeline-track.hpp @@ -56,6 +56,9 @@ public: const = 0; private: + + void on_title_menu_button(); + void on_remove_track(); private: @@ -68,12 +71,16 @@ private: Gtk::VBox headerWidget; + Gtk::Button titleMenuButton; + Gtk::ToolButton enableButton; Gtk::ToolButton lockButton; Gtk::Entry titleBox; Gtk::Toolbar buttonBar; + Gtk::Menu titleMenu; + Gtk::Menu contextMenu; }; From 2b8cd00ab5fa0c05b58b08b1262aed2b9400c77c Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Mon, 22 Dec 2008 17:00:15 +0100 Subject: [PATCH 044/214] yet another renaming. call it "Sync"... --- src/common/subsystemrunner.hpp | 2 +- src/lib/Makefile.am | 2 +- src/lib/allocationcluster.cpp | 12 ++++++------ src/lib/allocationcluster.hpp | 4 ++-- src/lib/singletonpolicies.hpp | 4 ++-- src/lib/{concurrency.hpp => sync.hpp} | 14 +++++++------- src/lib/visitordispatcher.hpp | 8 ++++---- src/proc/assetmanager.cpp | 6 +++--- src/proc/mobject/session/defsregistry.hpp | 6 +++--- tests/lib/Makefile.am | 1 + ...ency-locking-test.cpp => sync-locking-test.cpp} | 12 ++++++------ 11 files changed, 36 insertions(+), 35 deletions(-) rename src/lib/{concurrency.hpp => sync.hpp} (95%) rename tests/lib/{concurrency-locking-test.cpp => sync-locking-test.cpp} (95%) diff --git a/src/common/subsystemrunner.hpp b/src/common/subsystemrunner.hpp index ca81d1686..3b565de83 100644 --- a/src/common/subsystemrunner.hpp +++ b/src/common/subsystemrunner.hpp @@ -27,7 +27,7 @@ #include "include/error.hpp" #include "lib/util.hpp" #include "common/subsys.hpp" -#include "lib/concurrency.hpp" +#include "lib/sync.hpp" #include #include diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am index 6460a0f88..c44284f86 100644 --- a/src/lib/Makefile.am +++ b/src/lib/Makefile.am @@ -68,7 +68,7 @@ noinst_HEADERS += \ $(liblumiera_la_srcdir)/visitor.hpp \ $(liblumiera_la_srcdir)/visitordispatcher.hpp \ $(liblumiera_la_srcdir)/visitorpolicies.hpp \ - $(liblumiera_la_srcdir)/concurrency.hpp \ + $(liblumiera_la_srcdir)/sync.hpp \ $(liblumiera_la_srcdir)/p.hpp \ $(liblumiera_la_srcdir)/query.hpp \ $(liblumiera_la_srcdir)/singletonfactory.hpp \ diff --git a/src/lib/allocationcluster.cpp b/src/lib/allocationcluster.cpp index 06982df51..b5eb022ef 100644 --- a/src/lib/allocationcluster.cpp +++ b/src/lib/allocationcluster.cpp @@ -81,7 +81,7 @@ namespace lib { void AllocationCluster::MemoryManager::reset (TypeInfo info) { - Concurrency::ClassLock guard(); + Sync::ClassLock guard(); if (0 < mem_.size()) purge(); type_ = info; @@ -96,7 +96,7 @@ namespace lib { void AllocationCluster::MemoryManager::purge() { - Concurrency::ClassLock guard(); + Sync::ClassLock guard(); REQUIRE (type_.killIt, "we need a deleter function"); REQUIRE (0 < type_.allocSize, "allocation size unknown"); @@ -120,7 +120,7 @@ namespace lib { inline void* AllocationCluster::MemoryManager::allocate() { - Concurrency::ClassLock guard(); + Sync::ClassLock guard(); REQUIRE (0 < type_.allocSize); REQUIRE (top_ <= mem_.size()); @@ -140,7 +140,7 @@ namespace lib { inline void AllocationCluster::MemoryManager::commit (void* pendingAlloc) { - Concurrency::ClassLock guard(); + Sync::ClassLock guard(); REQUIRE (pendingAlloc); ASSERT (top_ < mem_.size()); @@ -175,7 +175,7 @@ namespace lib { { try { - Concurrency::ClassLock guard(); + Sync::ClassLock guard(); TRACE (memory, "shutting down AllocationCluster"); for (size_t i = typeHandlers_.size(); 0 < i; --i) @@ -214,7 +214,7 @@ namespace lib { ASSERT (0 < slot); { - Concurrency::ClassLock guard(); /////TODO: decide tradeoff: lock just the instance, or lock the AllocationCluster class? + Sync::ClassLock guard(); /////TODO: decide tradeoff: lock just the instance, or lock the AllocationCluster class? if (slot > typeHandlers_.size()) typeHandlers_.resize(slot); diff --git a/src/lib/allocationcluster.hpp b/src/lib/allocationcluster.hpp index dd7ce8959..1e63732cc 100644 --- a/src/lib/allocationcluster.hpp +++ b/src/lib/allocationcluster.hpp @@ -52,7 +52,7 @@ #include #include "include/error.hpp" -#include "lib/concurrency.hpp" +#include "lib/sync.hpp" #include "lib/scopedholder.hpp" #include "lib/scopedholdertransfer.hpp" @@ -222,7 +222,7 @@ namespace lib { static TypeInfo setup() { - Concurrency::ClassLock guard(); + Sync::ClassLock guard(); if (!id_) id_= ++maxTypeIDs; diff --git a/src/lib/singletonpolicies.hpp b/src/lib/singletonpolicies.hpp index afbb87253..d0bade0e1 100644 --- a/src/lib/singletonpolicies.hpp +++ b/src/lib/singletonpolicies.hpp @@ -34,7 +34,7 @@ This code is heavily inspired by #ifndef LUMIERA_SINGLETONPOLICIES_H #define LUMIERA_SINGLETONPOLICIES_H -#include "lib/concurrency.hpp" +#include "lib/sync.hpp" #include "include/error.hpp" #include @@ -139,7 +139,7 @@ namespace lumiera struct Multithreaded { typedef volatile S VolatileType; - typedef lib::Concurrency::ClassLock Lock; + typedef lib::Sync::ClassLock Lock; }; diff --git a/src/lib/concurrency.hpp b/src/lib/sync.hpp similarity index 95% rename from src/lib/concurrency.hpp rename to src/lib/sync.hpp index d54952988..123bb06c7 100644 --- a/src/lib/concurrency.hpp +++ b/src/lib/sync.hpp @@ -21,7 +21,7 @@ */ -/** @file concurrency.hpp +/** @file sync.hpp ** Collection of helpers and wrappers to support dealing with concurrency issues. ** Actually, everything is implemented either by the Lumiera backend, or directly ** by pthread. The purpose is to support and automate the most common use cases @@ -95,7 +95,7 @@ namespace lib { * * @todo actually implement this facility using the Lumiera backend. */ - struct Concurrency + struct Sync { struct Monitor { @@ -114,7 +114,7 @@ namespace lib { template static inline Monitor& getMonitor(); - static inline Monitor& getMonitor(Concurrency* forThis); + static inline Monitor& getMonitor(Sync* forThis); class Lock @@ -150,16 +150,16 @@ namespace lib { - Concurrency::Monitor& - Concurrency::getMonitor(Concurrency* forThis) + Sync::Monitor& + Sync::getMonitor(Sync* forThis) { REQUIRE (forThis); return forThis->objectMonitor_; } template - Concurrency::Monitor& - Concurrency::getMonitor() + Sync::Monitor& + Sync::getMonitor() { //TODO: a rather obscure race condition is hidden here: //TODO: depending on the build order, the dtor of this static variable may be called, while another thread is still holding an ClassLock. diff --git a/src/lib/visitordispatcher.hpp b/src/lib/visitordispatcher.hpp index de56445b9..7977d7003 100644 --- a/src/lib/visitordispatcher.hpp +++ b/src/lib/visitordispatcher.hpp @@ -26,7 +26,7 @@ #define LUMIERA_VISITORDISPATCHER_H #include "include/error.hpp" -#include "lib/concurrency.hpp" +#include "lib/sync.hpp" #include "lib/singleton.hpp" #include "lib/util.hpp" @@ -36,7 +36,7 @@ namespace lumiera { namespace visitor { - using lib::Concurrency; + using lib::Sync; template class Tag; @@ -62,7 +62,7 @@ namespace lumiera { static void generateID (size_t& id) { - Concurrency::ClassLock guard(); + Sync::ClassLock guard(); if (!id) id = ++lastRegisteredID; } @@ -138,7 +138,7 @@ namespace lumiera { void accomodate (size_t index) { - Concurrency::ClassLock guard(); + Sync::ClassLock guard(); if (index > table_.size()) table_.resize (index); // performance bottleneck?? TODO: measure the real impact! } diff --git a/src/proc/assetmanager.cpp b/src/proc/assetmanager.cpp index 24b39dfbc..960699189 100644 --- a/src/proc/assetmanager.cpp +++ b/src/proc/assetmanager.cpp @@ -24,7 +24,7 @@ #include "proc/assetmanager.hpp" #include "proc/asset/db.hpp" -#include "lib/concurrency.hpp" +#include "lib/sync.hpp" #include "lib/util.hpp" #include @@ -39,7 +39,7 @@ using boost::bind; using util::for_each; using lumiera::Singleton; -using lib::Concurrency; +using lib::Sync; namespace asset @@ -116,7 +116,7 @@ namespace asset TODO ("check validity of Ident Category"); ID asset_id (getID (idi)); - Concurrency::ClassLock guard(); + Sync::ClassLock guard(); TODO ("handle duplicate Registrations"); P smart_ptr (obj, &destroy); diff --git a/src/proc/mobject/session/defsregistry.hpp b/src/proc/mobject/session/defsregistry.hpp index 8a3fcdfd5..ad4721b04 100644 --- a/src/proc/mobject/session/defsregistry.hpp +++ b/src/proc/mobject/session/defsregistry.hpp @@ -40,7 +40,7 @@ #define MOBJECT_SESSION_DEFSREGISTRY_H -#include "lib/concurrency.hpp" +#include "lib/sync.hpp" #include "lib/query.hpp" #include "lib/util.hpp" #include "lib/p.hpp" @@ -58,7 +58,7 @@ namespace mobject { using lumiera::P; using lumiera::Query; - using lib::Concurrency; + using lib::Sync; using std::tr1::weak_ptr; using std::string; @@ -162,7 +162,7 @@ namespace mobject { static void createSlot (Table& table) { - Concurrency::ClassLock guard(); + Sync::ClassLock guard(); if (!index) index = ++maxSlots; if (index > table.size()) diff --git a/tests/lib/Makefile.am b/tests/lib/Makefile.am index b1366bf3f..19a13ce2f 100644 --- a/tests/lib/Makefile.am +++ b/tests/lib/Makefile.am @@ -58,6 +58,7 @@ test_lib_SOURCES = \ $(testlib_srcdir)/singletontestmocktest.cpp \ $(testlib_srcdir)/streamtypebasicstest.cpp \ $(testlib_srcdir)/streamtypelifecycletest.cpp \ + $(testlib_srcdir)/sync-locking-test.cpp \ $(testlib_srcdir)/test/cmdlinewrappertest.cpp \ $(testlib_srcdir)/test/testoptiontest.cpp \ $(testlib_srcdir)/vectortransfertest.cpp \ diff --git a/tests/lib/concurrency-locking-test.cpp b/tests/lib/sync-locking-test.cpp similarity index 95% rename from tests/lib/concurrency-locking-test.cpp rename to tests/lib/sync-locking-test.cpp index 32f1eb744..884b030e7 100644 --- a/tests/lib/concurrency-locking-test.cpp +++ b/tests/lib/sync-locking-test.cpp @@ -1,5 +1,5 @@ /* - ConcurrencyLocking(Test) - check the monitor object based locking + SyncLocking(Test) - check the monitor object based locking Copyright (C) Lumiera.org 2008, Hermann Vosseler @@ -24,7 +24,7 @@ #include "lib/test/run.hpp" #include "include/error.hpp" -#include "lib/concurrency.hpp" +#include "lib/sync.hpp" #include @@ -48,7 +48,7 @@ namespace lib { class Victim - : public Concurrency + : public Sync { volatile long cnt_[NUM_COUNTERS]; volatile uint step_; ///< @note stored as instance variable @@ -166,9 +166,9 @@ namespace lib { * But because the class Victim uses an object level monitor to * guard the mutations, the state should remain consistent. * - * @see concurrency.hpp + * @see sync.hpp */ - class ConcurrencyLocking_test : public Test + class SyncLocking_test : public Test { virtual void @@ -198,7 +198,7 @@ namespace lib { /** Register this test class... */ - LAUNCHER (ConcurrencyLocking_test, "unit common"); + LAUNCHER (SyncLocking_test, "unit common"); From 43521e394547db4ca851e814da4c5f3924d9a2e3 Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Tue, 23 Dec 2008 00:03:04 +0100 Subject: [PATCH 045/214] building block for the Condition part of the Monitor pattern --- src/lib/sync.hpp | 65 +++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 56 insertions(+), 9 deletions(-) diff --git a/src/lib/sync.hpp b/src/lib/sync.hpp index 123bb06c7..27b72f5c3 100644 --- a/src/lib/sync.hpp +++ b/src/lib/sync.hpp @@ -39,6 +39,7 @@ #include "include/nobugcfg.h" #include "lib/util.hpp" +#include "include/error.hpp" extern "C" { #include "lib/mutex.h" @@ -46,7 +47,8 @@ extern "C" { } #include - +#include +#include namespace lib { @@ -54,30 +56,75 @@ namespace lib { using boost::scoped_ptr; - namespace sync { // Helpers for Monitor based synchronisation + /** Helpers and building blocks for Monitor based synchronisation */ + namespace sync { + class RecMutex { lumiera_mutex mtx_; - public: - RecMutex() { lumiera_recmutex_init (&mtx_, "Obj.Monitor RecMutex", &NOBUG_FLAG (sync)); } - ~RecMutex() { lumiera_mutex_destroy (&mtx_, &NOBUG_FLAG (sync)); } + pthread_mutex_t* get () { return &mtx_.mutex; } + friend class Condition; - void acquire() + public: + RecMutex() { lumiera_recmutex_init (&mtx_, "Obj.Monitor RecMutex", &NOBUG_FLAG(sync)); } + ~RecMutex() { lumiera_mutex_destroy (&mtx_, &NOBUG_FLAG(sync)); } + + void + acquire() { TODO ("Record we may block on mutex"); - if (pthread_mutex_lock (&mtx_.mutex)) + if (pthread_mutex_lock (get())) throw lumiera::error::State("Mutex acquire failed."); ///////TODO capture the error-code TODO ("Record we successfully acquired the mutex"); } - void release() + + void + release() { TODO ("Record we are releasing the mutex"); - pthread_mutex_unlock (&mtx_.mutex); + pthread_mutex_unlock (get()); } + + }; + + + class Condition + { + lumiera_condition cond_; + + public: + Condition() { lumiera_condition_init (&cond_, "Obj.Monitor Condition", &NOBUG_FLAG(sync) ); } + ~Condition() { lumiera_condition_destroy (&cond_, &NOBUG_FLAG(sync) ); } + + void + signal (bool wakeAll=false) + { + if (wakeAll) + pthread_cond_broadcast (&cond_.cond); + else + pthread_cond_signal (&cond_.cond); + } + + template + bool + wait (volatile BF const& predicate, RecMutex& mtx, timespec* waitEndTime=0) + { + int err=0; + while (!predicate() && !err) + if (waitEndTime) + err = pthread_cond_timedwait (&cond_.cond, mtx.get(), waitEndTime); + else + err = pthread_cond_wait (&cond_.cond, mtx.get()); + + if (!err) return true; + if (ETIMEDOUT==err) return false; + + throw lumiera::error::State ("Condition wait failed."); ///////////TODO extract error-code + } }; } // namespace sync From 59a7270f5dd06017021eb08bf61bfe7b8214ea9b Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Tue, 23 Dec 2008 01:32:01 +0100 Subject: [PATCH 046/214] draft test for wait/notify, fails without the implementation --- src/lib/sync.hpp | 2 + tests/lib/sync-waiting-test.cpp | 163 ++++++++++++++++++++++++++++++++ 2 files changed, 165 insertions(+) create mode 100644 tests/lib/sync-waiting-test.cpp diff --git a/src/lib/sync.hpp b/src/lib/sync.hpp index 27b72f5c3..d614c96f1 100644 --- a/src/lib/sync.hpp +++ b/src/lib/sync.hpp @@ -147,6 +147,8 @@ namespace lib { struct Monitor { sync::RecMutex mtx_; + sync::Condition cond_; + Monitor() {} ~Monitor() {} diff --git a/tests/lib/sync-waiting-test.cpp b/tests/lib/sync-waiting-test.cpp new file mode 100644 index 000000000..5a0a69a04 --- /dev/null +++ b/tests/lib/sync-waiting-test.cpp @@ -0,0 +1,163 @@ +/* + SyncWaiting(Test) - check the monitor object based wait/notification + + Copyright (C) Lumiera.org + 2008, Hermann Vosseler + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +* *****************************************************/ + + +#include "lib/test/run.hpp" +#include "include/error.hpp" + +#include "lib/sync.hpp" + +#include + +#include + +using std::cout; +using test::Test; + + +namespace lib { + namespace test { + + namespace { // private test classes and data... + + + /** Interface defining the basic interaction pattern for this test */ + class Token + { + public: + + /** blocking concurrent operation */ + virtual void getIt() =0; + + /** start the notification chain */ + virtual void provide (uint val) =0; + + /** harvesting the result...*/ + uint result () { return sum_; } + + + protected: + volatile uint sum_, input_; + + virtual ~Token() {} + + Token() : sum_(0), input_(0) {} + }; + + + class SyncOnBool + : public Token + { + bool got_new_data_; + + public: + SyncOnBool() : got_new_data_ (false) {} + + void getIt() + { + //Lock(*this).wait (got_new_data_); + sum_ += input_; + } + + void provide (uint val) + { + //Lock sync(*this); + input_ = val; + got_new_data_ = true; + //sync.notifyAll(); + } + }; + + } // (End) test classes and data.... + + + + + + + + + + + /**************************************************************************** + * @test concurrent waiting and notification, implemented via object monitor. + * This test covers the second part of the monitor pattern, which builds upon + * the locking part an additionally uses an embedded condition. We provide + * several pre-configured ways of specifying the condition to wait upon. + * + * @see sync.hpp + */ + class SyncWaiting_test : public Test + { + + virtual void + run (Arg) + { + if (!Glib::thread_supported()) + Glib::thread_init(); + + SyncOnBool use_sync_var; + waitPingPong (use_sync_var); + } + + + /** + * Helper actually performing the test: + * creates two threads and let them block and wait cross-wise. + * @param tok object containing the monitor and condition to be tested. + */ + void + waitPingPong (Token& tok) + { + Glib::Thread *ping, *pong; + + ping = Glib::Thread::create(sigc::mem_fun(tok, &Token::getIt), true); + pong = Glib::Thread::create(sigc::mem_fun(tok, &Token::getIt), true); + + ASSERT (ping); + ASSERT (pong); + ASSERT (0 == tok.result()); + + sleep (1); // if the threads don't block correctly, they've missed their chance by now... + + // kick off the notification cascade... + uint val = (rand() % 1000); + tok.provide (val); + + // wait for the two Threads to finish their handshake + pong->join(); + ping->join(); + + ASSERT (2*val == tok.result()); + } + }; + + + + /** Register this test class... */ + LAUNCHER (SyncWaiting_test, "unit common"); + + + + } // namespace test + +} // namespace lumiera From 36704a856ee5665b4cdecd953dd9033b36692946 Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Tue, 23 Dec 2008 04:27:11 +0100 Subject: [PATCH 047/214] basic wait/notify impl added, waiting-test pass --- src/common/subsys.cpp | 2 +- src/common/subsystemrunner.hpp | 11 ++--- src/lib/sync.hpp | 76 ++++++++++++++++++++++----------- tests/lib/sync-waiting-test.cpp | 9 ++-- 4 files changed, 63 insertions(+), 35 deletions(-) diff --git a/src/common/subsys.cpp b/src/common/subsys.cpp index 41f2fb845..44fc9075d 100644 --- a/src/common/subsys.cpp +++ b/src/common/subsys.cpp @@ -53,7 +53,7 @@ namespace lumiera { bool Subsys::isRunning() { - //Lock guard (*this); + //Lock guard (this); return checkRunningState(); } diff --git a/src/common/subsystemrunner.hpp b/src/common/subsystemrunner.hpp index 3b565de83..da1d39360 100644 --- a/src/common/subsystemrunner.hpp +++ b/src/common/subsystemrunner.hpp @@ -87,6 +87,7 @@ namespace lumiera { * @see main.cpp */ class SubsystemRunner +// : Sync { Option& opts_; volatile bool emergency_; @@ -108,7 +109,7 @@ namespace lumiera { void maybeRun (Subsys& susy) { - //Lock guard (*this); + //Lock guard (this); if (!susy.isRunning() && susy.shouldStart (opts_)) triggerStartup (&susy); @@ -119,14 +120,14 @@ namespace lumiera { void shutdownAll () { - //Lock guard (*this); + //Lock guard (this); for_each (running_, killIt_); } bool wait () { - //Lock(*this).wait (&SubsystemRunner::allDead); + //Lock(this).wait (&SubsystemRunner::allDead); return isEmergencyExit(); } @@ -160,7 +161,7 @@ namespace lumiera { sigTerm (Subsys* susy, Error* problem) ///< called from subsystem on termination { ASSERT (susy); - //Lock guard (*this); + //Lock guard (this); triggerEmergency(problem); ERROR_IF (susy->isRunning(), lumiera, "Subsystem '%s' signals termination, " "without resetting running state", cStr(*susy)); @@ -173,7 +174,7 @@ namespace lumiera { allDead () { if (isEmergencyExit()) - ; //Lock(*this).setTimeout(EMERGENCYTIMEOUT); + ; //Lock(this).setTimeout(EMERGENCYTIMEOUT); return isnil (running_); // end wait if no running subsystem left } diff --git a/src/lib/sync.hpp b/src/lib/sync.hpp index d614c96f1..47dc591ec 100644 --- a/src/lib/sync.hpp +++ b/src/lib/sync.hpp @@ -97,7 +97,7 @@ namespace lib { lumiera_condition cond_; public: - Condition() { lumiera_condition_init (&cond_, "Obj.Monitor Condition", &NOBUG_FLAG(sync) ); } + Condition() { lumiera_condition_init (&cond_, "Obj.Monitor Condition", &NOBUG_FLAG(sync) ); } ~Condition() { lumiera_condition_destroy (&cond_, &NOBUG_FLAG(sync) ); } void @@ -109,9 +109,10 @@ namespace lib { pthread_cond_signal (&cond_.cond); } + template bool - wait (volatile BF const& predicate, RecMutex& mtx, timespec* waitEndTime=0) + wait (BF& predicate, RecMutex& mtx, timespec* waitEndTime=0) { int err=0; while (!predicate() && !err) @@ -127,6 +128,43 @@ namespace lib { } }; + + struct Monitor + { + sync::RecMutex mtx_; + sync::Condition cond_; + + Monitor() {} + ~Monitor() {} + + void acquireLock() { mtx_.acquire(); } + void releaseLock() { mtx_.release(); } + + void signal(bool a){ cond_.signal(a);} + + inline bool wait (volatile bool&, ulong); + }; + + + typedef volatile bool& Flag; + + struct BoolFlagPredicate + { + Flag flag_; + BoolFlagPredicate (Flag f) : flag_(f) {} + + bool operator() () { return flag_; } + }; + + + bool + Monitor::wait(Flag flag, ulong timeoout) + { + BoolFlagPredicate checkFlag(flag); + return cond_.wait(checkFlag, mtx_, (timespec*)0); + } + + } // namespace sync @@ -144,17 +182,7 @@ namespace lib { */ struct Sync { - struct Monitor - { - sync::RecMutex mtx_; - sync::Condition cond_; - - Monitor() {} - ~Monitor() {} - - void acquireLock() { mtx_.acquire(); } - void releaseLock() { mtx_.release(); } - }; + typedef sync::Monitor Monitor; Monitor objectMonitor_; @@ -169,24 +197,22 @@ namespace lib { class Lock { Monitor& mon_; + public: template - Lock(X* it) : mon_(getMonitor(it)) - { - mon_.acquireLock(); - } + Lock(X* it) : mon_(getMonitor(it)){ mon_.acquireLock(); } + Lock(Monitor& m) : mon_(m) { mon_.acquireLock(); } + ~Lock() { mon_.releaseLock(); } - Lock(Monitor& m) : mon_(m) - { - mon_.acquireLock(); - } + template + bool wait (C& cond, ulong time=0) { return mon_.wait(cond,time);} + + void notifyAll() { mon_.signal(true); } + void notify() { mon_.signal(false);} - ~Lock() - { - mon_.releaseLock(); - } }; + template struct ClassLock : Lock { diff --git a/tests/lib/sync-waiting-test.cpp b/tests/lib/sync-waiting-test.cpp index 5a0a69a04..3bc087258 100644 --- a/tests/lib/sync-waiting-test.cpp +++ b/tests/lib/sync-waiting-test.cpp @@ -65,7 +65,8 @@ namespace lib { class SyncOnBool - : public Token + : public Token, + public Sync { bool got_new_data_; @@ -74,16 +75,16 @@ namespace lib { void getIt() { - //Lock(*this).wait (got_new_data_); + Lock(this).wait (got_new_data_); sum_ += input_; } void provide (uint val) { - //Lock sync(*this); + Lock sync(this); input_ = val; got_new_data_ = true; - //sync.notifyAll(); + sync.notifyAll(); } }; From 7db0ba61d8568c5cebbce363e6ff33bc58f0267a Mon Sep 17 00:00:00 2001 From: Christian Thaeter Date: Tue, 23 Dec 2008 07:02:38 +0100 Subject: [PATCH 048/214] move tests from 'tests/lumiera' to 'tests/common' to reflect src layout --- tests/Makefile.am | 18 +++++++++++++----- tests/{lumiera => common}/hello_interface.h | 0 tests/{lumiera => common}/test-config.c | 0 tests/{lumiera => common}/test-interfaces.c | 2 +- tests/plugin/example_plugin.c | 2 +- 5 files changed, 15 insertions(+), 7 deletions(-) rename tests/{lumiera => common}/hello_interface.h (100%) rename tests/{lumiera => common}/test-config.c (100%) rename tests/{lumiera => common}/test-interfaces.c (99%) diff --git a/tests/Makefile.am b/tests/Makefile.am index 77a3db49f..3a2755ef2 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -60,12 +60,20 @@ test_filehandles_CPPFLAGS = $(AM_CPPFLAGS) -std=gnu99 -Wall -Werror test_filehandles_LDADD = liblumierabackend.la liblumiera.la $(NOBUGMT_LUMIERA_LIBS) liblumieracommon.la liblumieraproc.la -ldl -lboost_program_options-mt -lboost_regex-mt - - check_PROGRAMS += test-config -test_config_SOURCES = $(tests_srcdir)/lumiera/test-config.c +test_config_SOURCES = $(tests_srcdir)/common/test-config.c test_config_CPPFLAGS = $(AM_CPPFLAGS) -std=gnu99 -Wall -Werror -I$(top_srcdir)/src/ -test_config_LDADD = liblumiera.la $(LUMIERA_PLUGIN_LIBS) $(NOBUGMT_LUMIERA_LIBS) liblumieracommon.la liblumieraproc.la -ldl -lboost_program_options-mt -lboost_regex-mt +test_config_LDADD = \ + liblumieraproc.la \ + liblumieracommon.la \ + liblumiera.la \ + $(LUMIERA_PLUGIN_LIBS) \ + $(NOBUGMT_LUMIERA_LIBS) \ + -ldl \ + -lboost_program_options-mt \ + -lboost_regex-mt + + check_LTLIBRARIES += examplepluginc.la examplepluginc_la_SOURCES = $(tests_srcdir)/plugin/example_plugin.c @@ -73,7 +81,7 @@ examplepluginc_la_CPPFLAGS = $(AM_CPPFLAGS) -std=gnu99 -Wall -Werror -DLUMIERA_P examplepluginc_la_LDFLAGS = -module -avoid-version -no-undefined -rpath /dev/null check_PROGRAMS += test-interfaces -test_interfaces_SOURCES = $(tests_srcdir)/lumiera/test-interfaces.c +test_interfaces_SOURCES = $(tests_srcdir)/common/test-interfaces.c test_interfaces_CPPFLAGS = $(AM_CPPFLAGS) -std=gnu99 -Wall -Werror test_interfaces_LDADD = liblumiera.la $(LUMIERA_PLUGIN_LIBS) $(NOBUGMT_LUMIERA_LIBS) liblumieracommon.la liblumieraproc.la -ldl -lboost_program_options-mt -lboost_regex-mt test_interfaces_DEPENDENCIES = examplepluginc.la liblumiera.la diff --git a/tests/lumiera/hello_interface.h b/tests/common/hello_interface.h similarity index 100% rename from tests/lumiera/hello_interface.h rename to tests/common/hello_interface.h diff --git a/tests/lumiera/test-config.c b/tests/common/test-config.c similarity index 100% rename from tests/lumiera/test-config.c rename to tests/common/test-config.c diff --git a/tests/lumiera/test-interfaces.c b/tests/common/test-interfaces.c similarity index 99% rename from tests/lumiera/test-interfaces.c rename to tests/common/test-interfaces.c index e68153991..d11214af3 100644 --- a/tests/lumiera/test-interfaces.c +++ b/tests/common/test-interfaces.c @@ -26,7 +26,7 @@ #include "common/config_interface.h" #include "tests/test.h" -#include "tests/lumiera/hello_interface.h" +#include "tests/common/hello_interface.h" /* define 2 example interfaces diff --git a/tests/plugin/example_plugin.c b/tests/plugin/example_plugin.c index bd4a1f76d..60992745d 100644 --- a/tests/plugin/example_plugin.c +++ b/tests/plugin/example_plugin.c @@ -26,7 +26,7 @@ #include "common/interfacedescriptor.h" #include "common/config_interface.h" -#include "tests/lumiera/hello_interface.h" +#include "tests/common/hello_interface.h" LUMIERA_PLUGIN_INTERFACEHANDLE; From 8e1f64a2840262c4552791f0f4cfb3aebfc0168c Mon Sep 17 00:00:00 2001 From: Christian Thaeter Date: Tue, 23 Dec 2008 07:24:55 +0100 Subject: [PATCH 049/214] gui Makefile rework, remove _DEPENDENCIES vars _DEPENDENCIES supresses all automatic generated dependencies which is not what we wanted here, instead use dist_pkgdata_DATA which looks right. Add some clean rules to cleanup generated/copied data. I am not sure if this is completely right now, but looks (and works) much better than before. --- Makefile.am | 2 ++ icons/Makefile.am | 22 ++++++++++++---------- src/gui/Makefile.am | 22 ++++++++++------------ 3 files changed, 24 insertions(+), 22 deletions(-) diff --git a/Makefile.am b/Makefile.am index 842b7b464..a709c1230 100644 --- a/Makefile.am +++ b/Makefile.am @@ -27,9 +27,11 @@ check_LTLIBRARIES = pkglib_LTLIBRARIES = noinst_LTLIBRARIES = noinst_HEADERS = +dist_pkgdata_DATA = BUILT_SOURCES = EXTRA_DIST = SUBDIRS = +CLEANFILES = # global pre-processor flags. Per-target variables should include # these at the front (if possible) for consistency diff --git a/icons/Makefile.am b/icons/Makefile.am index d8ec425de..c4bb2c8ca 100644 --- a/icons/Makefile.am +++ b/icons/Makefile.am @@ -32,17 +32,19 @@ iconcommand = python $(top_srcdir)/admin/render-icon.py 32x32pre = $(prerendereddir)/32x32 48x48pre = $(prerendereddir)/48x48 -lumigui_DEPENDENCIES += \ - $(16x16)/tool-arrow.png $(22x22)/tool-arrow.png $(24x24)/tool-arrow.png $(32x32)/tool-arrow.png $(48x48)/tool-arrow.png \ - $(16x16)/tool-i-beam.png $(22x22)/tool-i-beam.png $(24x24)/tool-i-beam.png $(32x32)/tool-i-beam.png $(48x48)/tool-i-beam.png \ - $(16x16)/track-disabled.png \ - $(16x16)/track-enabled.png \ - $(16x16)/track-locked.png \ - $(16x16)/track-unlocked.png \ - $(16x16)/panel-assets.png $(22x22)/panel-assets.png $(32x32)/panel-assets.png \ - $(16x16)/panel-timeline.png \ +dist_pkgdata_DATA += \ + $(16x16)/tool-arrow.png $(22x22)/tool-arrow.png $(24x24)/tool-arrow.png $(32x32)/tool-arrow.png $(48x48)/tool-arrow.png \ + $(16x16)/tool-i-beam.png $(22x22)/tool-i-beam.png $(24x24)/tool-i-beam.png $(32x32)/tool-i-beam.png $(48x48)/tool-i-beam.png \ + $(16x16)/track-disabled.png \ + $(16x16)/track-enabled.png \ + $(16x16)/track-locked.png \ + $(16x16)/track-unlocked.png \ + $(16x16)/panel-assets.png $(22x22)/panel-assets.png $(32x32)/panel-assets.png \ + $(16x16)/panel-timeline.png \ $(16x16)/panel-viewer.png $(22x22)/panel-viewer.png $(32x32)/panel-viewer.png +clean-local: + rm -rf $(16x16) $(22x22) $(24x24) $(32x32) $(48x48) # ========== SVG Icons ========== @@ -73,7 +75,7 @@ $(22x22)/panel-assets.png: cp $(22x22pre)/panel-assets.png $(22x22) $(32x32)/panel-assets.png: cp $(32x32pre)/panel-assets.png $(32x32) - + $(16x16)/panel-timeline.png: cp $(16x16pre)/panel-timeline.png $(16x16) diff --git a/src/gui/Makefile.am b/src/gui/Makefile.am index fb73e3d29..fe1712a1a 100644 --- a/src/gui/Makefile.am +++ b/src/gui/Makefile.am @@ -46,17 +46,20 @@ lumigui_SOURCES = \ $(lumigui_srcdir)/gtk-lumiera.cpp \ $(lumigui_srcdir)/gtk-lumiera.hpp -lumigui_DEPENDENCIES = \ - $(top_builddir)/lumiera_ui.rc \ - $(top_builddir)/liblumieracommon.la \ - $(top_builddir)/liblumiera.la \ - $(top_builddir)/liblumierabackend.la \ - $(top_builddir)/liblumieraproc.la + +# +# themes, locales and other supplemental data +# +dist_pkgdata_DATA += lumiera_ui.rc +CLEANFILES += lumiera_ui.rc + +lumiera_ui.rc: + cp $(lumigui_srcdir)/lumiera_ui.rc $(top_builddir) + # # gtk_gui.lum becomes the pluginized gui # - pkglib_LTLIBRARIES += gtk_gui.la gtk_gui_la_CFLAGS = $(AM_CFLAGS) -std=gnu99 -Wall -Wextra -Werror @@ -169,9 +172,4 @@ libgui_la_LIBADD = \ $(NOBUGMT_LUMIERA_LIBS) -# -# themes, locales and other supplemental data -# -$(top_builddir)/lumiera_ui.rc: - cp $(lumigui_srcdir)/lumiera_ui.rc $(top_builddir) From 121599dc897e7a31fca1ff2973c9a431c57567a2 Mon Sep 17 00:00:00 2001 From: Christian Thaeter Date: Tue, 23 Dec 2008 08:44:30 +0100 Subject: [PATCH 050/214] lowest level thread api proposal --- src/backend/threads.c | 52 +++++++++++++++++++++ src/backend/threads.h | 102 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 154 insertions(+) create mode 100644 src/backend/threads.c create mode 100644 src/backend/threads.h diff --git a/src/backend/threads.c b/src/backend/threads.c new file mode 100644 index 000000000..9c051fc13 --- /dev/null +++ b/src/backend/threads.c @@ -0,0 +1,52 @@ +/* + threads.c - Manage threads + + Copyright (C) Lumiera.org + 2008, Christian Thaeter + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +//TODO: Support library includes// + + +//TODO: Lumiera header includes// +#include "backend/threads.h" + +//TODO: internal/static forward declarations// + + +//TODO: System includes// + + +/** + * @file + * + */ + +NOBUG_DEFINE_FLAG_PARENT (threads, /*TODO insert parent flag here */); + + +//code goes here// + + + +/* +// Local Variables: +// mode: C +// c-file-style: "gnu" +// indent-tabs-mode: nil +// End: +*/ diff --git a/src/backend/threads.h b/src/backend/threads.h new file mode 100644 index 000000000..38c0e12f7 --- /dev/null +++ b/src/backend/threads.h @@ -0,0 +1,102 @@ +/* + threads.h - Manage threads + + Copyright (C) Lumiera.org + 2008, Christian Thaeter + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef LUMIERA_THREADS_H +#define LUMIERA_THREADS_H + +//TODO: Support library includes// + + +//TODO: Forward declarations// + + +//TODO: Lumiera header includes// + + +//TODO: System includes// +#include + + +/** + * @file + * + */ + +//TODO: declarations go here// + +typedef struct lumiera_thread_struct lumiera_thread; +typedef lumiera_thread* LumieraThread; + +/** + * Thread classes. + * We define some 'classes' of threads for different purposes to abstract + * priorities and other attributes. + */ +enum lumiera_thread_class + { + /** mostly idle, low latency **/ + LUMIERA_THREAD_INTERACTIVE, + /** busy at average priority **/ + LUMIERA_THREAD_WORKER, + /** busy, soft realtime, high priority **/ + LUMIERA_THREAD_URGEND, + /** high latency, background jobs **/ + LUMIERA_THREAD_BATCH, + /** Something to do when there is really nothing else to do **/ + LUMIERA_THREAD_IDLE, + }; + +/** + * Start a thread. + * Threads are implemented as procedures which take a void* and dont return anything. + * When a thread wants to pass something back to the application it should use the void* it got for + * constructing the return. + * * Threads must complete (return from their thread function) + * * They must not call any exit() function. + * * Threads are not cancelable + * * Threads shall not handle signals (all signals will be disabled for them) unless explicitly acknowledged + * + * @param kind class of the thread to start + * @param start_routine pointer to a function to execute in a thread (returning void, not void* as in pthreads) + * @param arg generic pointer passed to the thread + * @param finished a condition variable to be broadcasted, if not NULL. + * The associated mutex should be locked at thread_run time already, else the signal can get lost. + * @param purpose descriptive name of this thread, used by NoBug + * @param flag NoBug flag used for logging the thread startup and return + */ +LumieraThread +lumiera_thread_run (enum lumiera_thread_class kind, + void (*start_routine)(void *), + void * arg, + LumieraCondition finished, + const char* purpose, + struct nobug_flag* flag); + + + +#endif +/* +// Local Variables: +// mode: C +// c-file-style: "gnu" +// indent-tabs-mode: nil +// End: +*/ From 2126b25604ea1d87d0db680e36b635ad8570681f Mon Sep 17 00:00:00 2001 From: Christian Thaeter Date: Tue, 23 Dec 2008 09:06:55 +0100 Subject: [PATCH 051/214] Flag to make thread jobs optional --- src/backend/threads.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/backend/threads.h b/src/backend/threads.h index 38c0e12f7..cca5594dd 100644 --- a/src/backend/threads.h +++ b/src/backend/threads.h @@ -62,6 +62,15 @@ enum lumiera_thread_class LUMIERA_THREAD_BATCH, /** Something to do when there is really nothing else to do **/ LUMIERA_THREAD_IDLE, + + /** + * flag to let the decision to run the function in a thread open to the backend. + * depending on load it might decide to run it sequentially. + * This has some constraints: + * The condition variable to signal the finish of the thread must not be used. + * The Thread must be very careful with locking, better don't. + **/ + LUMIERA_THREAD_OR_NOT = 1<<16 }; /** From c9d83d97c3afa271e8b38c8bb999250355779f53 Mon Sep 17 00:00:00 2001 From: Christian Thaeter Date: Wed, 24 Dec 2008 00:26:32 +0100 Subject: [PATCH 052/214] Moved the resourcecollector from backend to lib --- src/backend/Makefile.am | 15 --------------- src/lib/Makefile.am | 2 ++ src/{backend => lib}/resourcecollector.c | 2 +- src/{backend => lib}/resourcecollector.h | 0 tests/Makefile.am | 2 +- .../{backend => library}/test-resourcecollector.c | 2 +- 6 files changed, 5 insertions(+), 18 deletions(-) rename src/{backend => lib}/resourcecollector.c (98%) rename src/{backend => lib}/resourcecollector.h (100%) rename tests/{backend => library}/test-resourcecollector.c (97%) diff --git a/src/backend/Makefile.am b/src/backend/Makefile.am index 201bcac0a..75bcc0d7e 100644 --- a/src/backend/Makefile.am +++ b/src/backend/Makefile.am @@ -28,7 +28,6 @@ liblumierabackend_la_SOURCES = \ $(liblumierabackend_la_srcdir)/file.c \ $(liblumierabackend_la_srcdir)/filehandle.c \ $(liblumierabackend_la_srcdir)/filedescriptor.c \ - $(liblumierabackend_la_srcdir)/resourcecollector.c \ $(liblumierabackend_la_srcdir)/mmap.c \ $(liblumierabackend_la_srcdir)/mmapings.c \ $(liblumierabackend_la_srcdir)/mmapcache.c \ @@ -44,19 +43,6 @@ noinst_HEADERS += \ $(liblumierabackend_la_srcdir)/filehandle.h \ $(liblumierabackend_la_srcdir)/filedescriptor.h \ $(liblumierabackend_la_srcdir)/filehandlecache.h \ - $(liblumierabackend_la_srcdir)/resourcecollector.h \ - $(liblumierabackend_la_srcdir)/mmap.h \ - $(liblumierabackend_la_srcdir)/mmapings.h \ - $(liblumierabackend_la_srcdir)/mmapcache.h - - -noinst_HEADERS += \ - $(liblumierabackend_la_srcdir)/backend.h \ - $(liblumierabackend_la_srcdir)/file.h \ - $(liblumierabackend_la_srcdir)/filehandle.h \ - $(liblumierabackend_la_srcdir)/filedescriptor.h \ - $(liblumierabackend_la_srcdir)/filehandlecache.h \ - $(liblumierabackend_la_srcdir)/resourcecollector.h \ $(liblumierabackend_la_srcdir)/mmap.h \ $(liblumierabackend_la_srcdir)/mmapings.h \ $(liblumierabackend_la_srcdir)/mmapcache.h @@ -65,7 +51,6 @@ noinst_HEADERS += \ $(liblumierabackend_la_srcdir)/filehandle.h \ $(liblumierabackend_la_srcdir)/filedescriptor.h \ $(liblumierabackend_la_srcdir)/filehandlecache.h \ - $(liblumierabackend_la_srcdir)/resourcecollector.h \ $(liblumierabackend_la_srcdir)/mmap.h \ $(liblumierabackend_la_srcdir)/mmapings.h \ $(liblumierabackend_la_srcdir)/mmapcache.h diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am index 4608feedb..d8c790269 100644 --- a/src/lib/Makefile.am +++ b/src/lib/Makefile.am @@ -32,6 +32,7 @@ liblumiera_la_SOURCES = \ $(liblumiera_la_srcdir)/psplay.c \ $(liblumiera_la_srcdir)/mrucache.c \ $(liblumiera_la_srcdir)/time.c \ + $(liblumiera_la_srcdir)/resourcecollector.c \ $(liblumiera_la_srcdir)/allocationcluster.cpp \ $(liblumiera_la_srcdir)/external/libgavl.cpp \ $(liblumiera_la_srcdir)/lumitime.cpp \ @@ -53,6 +54,7 @@ noinst_HEADERS += \ $(liblumiera_la_srcdir)/psplay.h \ $(liblumiera_la_srcdir)/mrucache.h \ $(liblumiera_la_srcdir)/time.h \ + $(liblumiera_la_srcdir)/resourcecollector.h \ $(liblumiera_la_srcdir)/ppmpl.h \ $(liblumiera_la_srcdir)/allocationcluster.hpp \ $(liblumiera_la_srcdir)/scopedholdertransfer.hpp \ diff --git a/src/backend/resourcecollector.c b/src/lib/resourcecollector.c similarity index 98% rename from src/backend/resourcecollector.c rename to src/lib/resourcecollector.c index 2e31c41c3..e9848d6f0 100644 --- a/src/backend/resourcecollector.c +++ b/src/lib/resourcecollector.c @@ -27,7 +27,7 @@ #include -NOBUG_DEFINE_FLAG_PARENT (resourcecollector, backend); +NOBUG_DEFINE_FLAG (resourcecollector); /* TODO: make this a hierachy, derrive from PARENT (library) ? */ llist lumiera_resourcecollector_registry[LUMIERA_RESOURCE_END]; lumiera_mutex lumiera_resourcecollector_lock; diff --git a/src/backend/resourcecollector.h b/src/lib/resourcecollector.h similarity index 100% rename from src/backend/resourcecollector.h rename to src/lib/resourcecollector.h diff --git a/tests/Makefile.am b/tests/Makefile.am index 3a2755ef2..2de2f44ba 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -92,7 +92,7 @@ test_filemmap_CPPFLAGS = $(AM_CPPFLAGS) -std=gnu99 -Wall -Werror -I$(top_srcdir) test_filemmap_LDADD = liblumierabackend.la liblumiera.la -lnobugmt -lpthread -ldl -lm liblumieracommon.la liblumieraproc.la -ldl -lboost_program_options-mt -lboost_regex-mt check_PROGRAMS += test-resourcecollector -test_resourcecollector_SOURCES = $(tests_srcdir)/backend/test-resourcecollector.c +test_resourcecollector_SOURCES = $(tests_srcdir)/library/test-resourcecollector.c test_resourcecollector_CPPFLAGS = $(AM_CPPFLAGS) -std=gnu99 -Wall -Werror -I$(top_srcdir)/src/ test_resourcecollector_LDADD = liblumierabackend.la liblumiera.la -lnobugmt -lpthread -ldl -lm liblumieracommon.la liblumieraproc.la -ldl -lboost_program_options-mt -lboost_regex-mt diff --git a/tests/backend/test-resourcecollector.c b/tests/library/test-resourcecollector.c similarity index 97% rename from tests/backend/test-resourcecollector.c rename to tests/library/test-resourcecollector.c index c0e8380a9..d3e6d8483 100644 --- a/tests/backend/test-resourcecollector.c +++ b/tests/library/test-resourcecollector.c @@ -19,7 +19,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include "backend/resourcecollector.h" +#include "lib/resourcecollector.h" #include "tests/test.h" From c0bc3cffb7e8c14775a3bef548746ad3bc97f29e Mon Sep 17 00:00:00 2001 From: Christian Thaeter Date: Wed, 24 Dec 2008 00:38:19 +0100 Subject: [PATCH 053/214] add a LUMIERA_RESOURCE_CPU to the resource-collector --- src/lib/resourcecollector.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/lib/resourcecollector.h b/src/lib/resourcecollector.h index 703da8b7b..863eec600 100644 --- a/src/lib/resourcecollector.h +++ b/src/lib/resourcecollector.h @@ -34,6 +34,8 @@ enum lumiera_resource LUMIERA_RESOURCE_MEMORY, /** OS filehandles **/ LUMIERA_RESOURCE_FILEHANDLE, + /** CPU time, as in threads and such **/ + LUMIERA_RESOURCE_CPU, /** mmaped regions **/ LUMIERA_RESOURCE_MMAP, /** disk space for the storage area, context is a pointer to the filename indication the device **/ From ee9cd8b63231d77fe4fc7f170faf30496e33684d Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Wed, 24 Dec 2008 03:30:34 +0100 Subject: [PATCH 054/214] typos --- src/include/error.hpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/include/error.hpp b/src/include/error.hpp index bce21423c..50d43187d 100644 --- a/src/include/error.hpp +++ b/src/include/error.hpp @@ -40,7 +40,7 @@ namespace lumiera { LUMIERA_ERROR_DECLARE(EXCEPTION); /** - * Interface and Baseclass of all Exceptions thrown + * Interface and Base class of all Exceptions thrown * from within Lumiera (C++) code. Common operations * for getting an diagnostic message and for obtaining * the root cause, i.e. the first exception encountered @@ -56,7 +56,7 @@ namespace lumiera { Error (const Error&) throw(); virtual ~Error () throw() {}; - /** yield a diagnostic message characterizing the problem */ + /** yield a diagnostic message characterising the problem */ virtual const char* what () const throw(); /** the internal Lumiera-error-ID (was set as C-errorstate in ctor) */ @@ -68,12 +68,12 @@ namespace lumiera { /** If this exception was caused by a chain of further exceptions, * return the description of the first one registered in this throw sequence. * This works only if every exceptions thrown as a consequence of another exception - * is propperly constructed by passing the original exception to the constructor + * is properly constructed by passing the original exception to the constructor * @return the description string, maybe empty (if there is no known root cause) */ const string& rootCause () const throw() { return this->cause_; } - /** replace the previous or default friendly message for the user. To be localized. */ + /** replace the previous or default friendly message for the user. To be localised. */ Error& setUsermsg (const string& newMsg) throw() { this->msg_ = newMsg; return *this; } /** give additional developer info. Typically used at intermediate handlers to add context. */ @@ -82,10 +82,10 @@ namespace lumiera { private: const char* id_; ///< an LUMIERA_ERROR id, which is set as errorstate on construction - string msg_; ///< friendly message intended for users (to be localized) + string msg_; ///< friendly message intended for users (to be localised) string desc_; ///< detailed description of the error situation for the developers mutable string what_; ///< buffer for generating the detailed description on demand - const string cause_; ///< descriptoin of first exception encountered in the chain + const string cause_; ///< description of first exception encountered in the chain static const string extractCauseMsg (const std::exception&) throw(); }; @@ -95,7 +95,7 @@ namespace lumiera { - /* === Exception Subcategories === */ + /* === Exception Sub-categories === */ namespace error { @@ -123,10 +123,10 @@ namespace lumiera { /** Macro for creating derived exception classes properly * integrated into Lumiera's exception hierarchy. Using - * this macro asures that the new class will get the full + * this macro assures that the new class will get the full * set of constructors and behaviour common to all exception * classes, so it should be used when creating an derived - * exception type for more then stricly local purposes + * exception type for more then strictly local purposes */ #define LUMIERA_EXCEPTION_DECLARE(CLASS, PARENT, _ID_) \ class CLASS : public PARENT \ From 2650216d9b8ab71816cbee73664a70cbca7b7444 Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Wed, 24 Dec 2008 03:31:35 +0100 Subject: [PATCH 055/214] Refactoring I: better put the timeout explicitly separate --- src/lib/sync.hpp | 80 +++++++++++++++++++++++++------- tests/lib/meta/generatortest.cpp | 2 +- 2 files changed, 65 insertions(+), 17 deletions(-) diff --git a/src/lib/sync.hpp b/src/lib/sync.hpp index 47dc591ec..7968b0df7 100644 --- a/src/lib/sync.hpp +++ b/src/lib/sync.hpp @@ -28,14 +28,15 @@ ** in object oriented style. ** ** @see mutex.h - ** @see concurrency-locking-test.cpp + ** @see sync-locking-test.cpp + ** @see sync-waiting-test.cpp ** @see asset::AssetManager::reg() usage example ** @see subsystemrunner.hpp usage example */ -#ifndef LIB_CONCURRENCY_H -#define LIB_CONCURRENCY_H +#ifndef LIB_SYNC_H +#define LIB_SYNC_H #include "include/nobugcfg.h" #include "lib/util.hpp" @@ -59,7 +60,8 @@ namespace lib { /** Helpers and building blocks for Monitor based synchronisation */ namespace sync { - + class Timeout; + class RecMutex { lumiera_mutex mtx_; @@ -110,14 +112,14 @@ namespace lib { } - template + template bool - wait (BF& predicate, RecMutex& mtx, timespec* waitEndTime=0) + wait (BF& predicate, MTX& mtx, Timeout& waitEndTime) { int err=0; while (!predicate() && !err) if (waitEndTime) - err = pthread_cond_timedwait (&cond_.cond, mtx.get(), waitEndTime); + err = pthread_cond_timedwait (&cond_.cond, mtx.get(), &waitEndTime); else err = pthread_cond_wait (&cond_.cond, mtx.get()); @@ -128,12 +130,49 @@ namespace lib { } }; - - struct Monitor + /** helper for specifying an optional timeout + * for an timed wait. It wraps a timespec-struct + * and allows for easy initialisation by a given + * relative offset. + */ + struct Timeout + : timespec { - sync::RecMutex mtx_; - sync::Condition cond_; + Timeout() { tv_sec=tv_nsec=0; } + /** initialise to NOW() + offset (in milliseconds) */ + Timeout& + setOffset (ulong offs) + { + if (offs) + { + clock_gettime(CLOCK_REALTIME, this); + tv_sec += offs / 1000; + tv_nsec += 1000000 * (offs % 1000); + if (tv_nsec > 1000000000) + { + tv_sec += tv_nsec / 1000000000; + tv_nsec %= 1000000000; + } } + return *this; + } + + operator bool() { return 0 != tv_sec; } // allows if (timeout_).... + }; + + + typedef volatile bool& Flag; + + class Monitor + { + RecMutex mtx_; + Condition cond_; + + Timeout timeout_; + + //////TODO my intention is to make two variants of the monitor, where the simple one leaves out the condition part + + public: Monitor() {} ~Monitor() {} @@ -142,11 +181,12 @@ namespace lib { void signal(bool a){ cond_.signal(a);} - inline bool wait (volatile bool&, ulong); + inline bool wait (Flag, ulong); + inline void setTimeout(ulong); + inline bool isTimedWait(); }; - typedef volatile bool& Flag; struct BoolFlagPredicate { @@ -158,12 +198,18 @@ namespace lib { bool - Monitor::wait(Flag flag, ulong timeoout) + Monitor::wait (Flag flag, ulong timedwait) { BoolFlagPredicate checkFlag(flag); - return cond_.wait(checkFlag, mtx_, (timespec*)0); + return cond_.wait(checkFlag, mtx_, timeout_.setOffset(timedwait)); } - + + void + Monitor::setTimeout (ulong relative) {timeout_.setOffset(relative);} + + bool + Monitor::isTimedWait () {return (timeout_);} + } // namespace sync @@ -206,6 +252,7 @@ namespace lib { template bool wait (C& cond, ulong time=0) { return mon_.wait(cond,time);} + void setTimeout(ulong time) { mon_.setTimeout(time); } void notifyAll() { mon_.signal(true); } void notify() { mon_.signal(false);} @@ -240,6 +287,7 @@ namespace lib { //TODO: depending on the build order, the dtor of this static variable may be called, while another thread is still holding an ClassLock. //TODO: An possible solution would be to use an shared_ptr to the Monitor in case of a ClassLock and to protect access with another Mutex. //TODO. But I am really questioning if we can't ignore this case and state: "don't hold a ClassLock when your code maybe still running in shutdown phase!" + //TODO: probably best Idea is to detect this situation in DEBUG or ALPHA mode static scoped_ptr classMonitor_ (0); if (!classMonitor_) classMonitor_.reset (new Monitor ()); diff --git a/tests/lib/meta/generatortest.cpp b/tests/lib/meta/generatortest.cpp index 932b79fe0..c4224b4fa 100644 --- a/tests/lib/meta/generatortest.cpp +++ b/tests/lib/meta/generatortest.cpp @@ -120,7 +120,7 @@ namespace lumiera */ class TypeListGenerator_test : public Test { - virtual void run(Arg arg) + virtual void run(Arg) { NumberBabbler me_can_has_more_numberz; From 7e13ca33d599efd964c3efe608c82e161cdf4fb5 Mon Sep 17 00:00:00 2001 From: Christian Thaeter Date: Wed, 24 Dec 2008 03:40:55 +0100 Subject: [PATCH 056/214] Condition Variable makeover * Improved the Documentation * add an CONDITION_UNLOCK macro to exoplicitly unlock the condition mutex * Add ENSUREs to check that the mutex is locked * Fix the CONDITION_WAIT, takes the missing condition expression now * Fix, document and improve SIGNAL and BROADCAST macros * remove the signal and broadcast functions --- src/lib/condition.h | 103 ++++++++++++++++++++++++-------------------- 1 file changed, 56 insertions(+), 47 deletions(-) diff --git a/src/lib/condition.h b/src/lib/condition.h index 3bdbcbedc..6e68409bd 100644 --- a/src/lib/condition.h +++ b/src/lib/condition.h @@ -39,6 +39,8 @@ LUMIERA_ERROR_DECLARE (CONDITION_DESTROY); * Condition section. * Locks the condition mutex, one can use LUMIERA_CONDITION_WAIT to wait for signals or * LUMIERA_CONDITION_SIGNAL or LUMIERA_CONDITION_BROADCAST to wake waiting threads + * @param nobugflag NoBug flag used to log actions on the condition + * @param cnd Condition variable to be locked */ #define LUMIERA_CONDITION_SECTION(nobugflag, cnd) \ for (lumiera_conditionacquirer NOBUG_CLEANUP(lumiera_conditionacquirer_ensureunlocked) \ @@ -55,24 +57,64 @@ LUMIERA_ERROR_DECLARE (CONDITION_DESTROY); }); \ lumiera_condition_section_.condition; \ ({ \ - if (lumiera_condition_section_.condition) \ - { \ - pthread_mutex_unlock (&lumiera_condition_section_.condition->mutex); \ - lumiera_condition_section_.condition = NULL; \ - RESOURCE_LEAVE(nobugflag, lumiera_condition_section_.rh); \ - } \ + LUMIERA_CONDITION_UNLOCK(nobugflag) \ })) -#define LUMIERA_CONDITION_WAIT \ + +/** + * Explicit mutex unlock for a condition variable + * One can early unlock the mutex of a condition variable prior leaving a CONDITION_SECTION. + * The CONDITION_WAIT, CONDITION_SIGNAL and CONDITION_BROADCAST macros must not be used after the mutex + * got unlocked. + * @param nobugflag NoBug flag used to log actions on the condition + */ +#define LUMIERA_CONDITION_UNLOCK \ + if (lumiera_condition_section_.condition) \ + { \ + pthread_mutex_unlock (&lumiera_condition_section_.condition->mutex); \ + lumiera_condition_section_.condition = NULL; \ + RESOURCE_LEAVE(nobugflag, lumiera_condition_section_.rh); \ + } + + +/** + * Wait for a condition. + * Must be used inside a CONDITION_SECTION. + * @param expr Conditon which must become true, else the condition variable goes back into sleep + */ +#define LUMIERA_CONDITION_WAIT(expr) \ do { \ - NOBUG_RESOURCE_STATE_RAW (lumiera_condition_section_.flag, lumiera_condition_section_.rh, NOBUG_RESOURCEING); \ - pthread_cond_wait (&lumiera_condition_section_.condition->cond, &lumiera_condition_section_.condition->mutex); \ - NOBUG_RESOURCE_STATE_RAW (lumiera_condition_section_.flag, lumiera_condition_section_.rh, NOBUG_RESOURCE_EXCLUSIVE); \ - while (0) + ENSURE (lumiera_condition_section_.condition, "Condition mutex not locked"); \ + NOBUG_RESOURCE_STATE_RAW (lumiera_condition_section_.flag, lumiera_condition_section_.rh, NOBUG_RESOURCE_WAITING); \ + pthread_cond_wait (&lumiera_condition_section_.condition->cond, &lumiera_condition_section_.condition->mutex); \ + NOBUG_RESOURCE_STATE_RAW (lumiera_condition_section_.flag, lumiera_condition_section_.rh, NOBUG_RESOURCE_EXCLUSIVE);\ + } while (!(expr)) -#define LUMIERA_CONDITION_SIGNAL (nobugflag) pthread_cond_signal (&lumiera_condition_section_.condition->cond) -#define LUMIERA_CONDITION_BROADCAST (nobugflag) pthread_cond_broadcast (&lumiera_condition_section_.condition->cond) +/** + * Signal a condition variable + * Must be used inside a CONDITION_SECTION. + * Wakes one thread waiting on the condition variable + */ +#define LUMIERA_CONDITION_SIGNAL \ +do { \ + ENSURE (lumiera_condition_section_.condition, "Condition mutex not locked"); \ + NOBUG_IF(NOBUG_MODE_ALPHA, TRACE(lumiera_condition_section_.flag, "Signaling")); \ + pthread_cond_signal (&lumiera_condition_section_.condition->cond); \ +} while (0) + + +/** + * Broadcast a condition variable + * Must be used inside a CONDITION_SECTION. + * Wakes all threads waiting on the condition variable + */ +#define LUMIERA_CONDITION_BROADCAST \ +do { \ + ENSURE (lumiera_condition_section_.condition, "Condition mutex not locked"); \ + NOBUG_IF(NOBUG_MODE_ALPHA, TRACE(lumiera_condition_section_.flag, "Broadcasting")); \ + pthread_cond_broadcast (&lumiera_condition_section_.condition->cond); \ +} while (0) @@ -108,40 +150,6 @@ LumieraCondition lumiera_condition_destroy (LumieraCondition self, struct nobug_flag* flag); -/** - * signal a single waiting thread. - * @param self condition variable to be signaled, must be given, all errors are fatal - */ -static inline void -lumiera_condition_signal (LumieraCondition self) -{ - REQUIRE (self); - if (pthread_mutex_lock (&self->mutex)) - LUMIERA_DIE (MUTEX_LOCK); - pthread_cond_signal (&self->cond); - if (pthread_mutex_unlock (&self->mutex)) - LUMIERA_DIE (MUTEX_UNLOCK); -} - -/** - * signal all waiting threads - * @param self condition variable to be signaled, must be given, all errors are fatal - */ -static inline void -lumiera_condition_broadcast (LumieraCondition self) -{ - REQUIRE (self); - if (pthread_mutex_lock (&self->mutex)) - LUMIERA_DIE (MUTEX_LOCK); - pthread_cond_broadcast (&self->cond); - if (pthread_mutex_unlock (&self->mutex)) - LUMIERA_DIE (MUTEX_UNLOCK); -} - - - - - /** * conditionacquirer used to manage the state of a condition variable. */ @@ -154,6 +162,7 @@ struct lumiera_conditionacquirer_struct typedef struct lumiera_conditionacquirer_struct lumiera_conditionacquirer; typedef struct lumiera_conditionacquirer_struct* LumieraConditionacquirer; + /* helper function for nobug */ static inline void lumiera_conditionacquirer_ensureunlocked (LumieraConditionacquirer self) From be2daf64ff7c815c80d37152d8c940f4fa202d93 Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Wed, 24 Dec 2008 03:42:36 +0100 Subject: [PATCH 057/214] whitespace (trying to compare LUMIERA_MUTEX_SECTION and LUMIERA_RECMUTEX_SECTION) --- src/lib/mutex.h | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/src/lib/mutex.h b/src/lib/mutex.h index 86fb48944..0111c9fff 100644 --- a/src/lib/mutex.h +++ b/src/lib/mutex.h @@ -101,26 +101,26 @@ LUMIERA_ERROR_DECLARE (MUTEX_DESTROY); /** * Recursive Mutual exclusive section. */ -#define LUMIERA_RECMUTEX_SECTION(nobugflag, mtx) \ - for (lumiera_mutexacquirer NOBUG_CLEANUP(lumiera_mutexacquirer_ensureunlocked) lumiera_mutex_section_ = {(LumieraMutex)1 \ - NOBUG_RESOURCE_HANDLE_COMMA_INITIALIZER}; \ - lumiera_mutex_section_.mutex;) \ - for ( \ - ({ \ - lumiera_mutex_section_.mutex = (mtx); \ - NOBUG_RESOURCE_HANDLE_INIT (lumiera_mutex_section_.rh); \ - RESOURCE_ENTER (nobugflag, (mtx)->rh, "acquire recmutex", &lumiera_mutex_section_, \ - NOBUG_RESOURCE_RECURSIVE, lumiera_mutex_section_.rh); \ - if (pthread_mutex_lock (&(mtx)->mutex)) LUMIERA_DIE (MUTEX_LOCK); \ - }); \ - lumiera_mutex_section_.mutex; \ - ({ \ - if (lumiera_mutex_section_.mutex) \ - { \ - pthread_mutex_unlock (&lumiera_mutex_section_.mutex->mutex); \ - lumiera_mutex_section_.mutex = NULL; \ - RESOURCE_LEAVE(nobugflag, lumiera_mutex_section_.rh); \ - } \ +#define LUMIERA_RECMUTEX_SECTION(nobugflag, mtx) \ + for (lumiera_mutexacquirer NOBUG_CLEANUP(lumiera_mutexacquirer_ensureunlocked) lumiera_mutex_section_ \ + = {(LumieraMutex)1 NOBUG_RESOURCE_HANDLE_COMMA_INITIALIZER}; \ + lumiera_mutex_section_.mutex;) \ + for ( \ + ({ \ + lumiera_mutex_section_.mutex = (mtx); \ + NOBUG_RESOURCE_HANDLE_INIT (lumiera_mutex_section_.rh); \ + RESOURCE_ENTER (nobugflag, (mtx)->rh, "acquire recmutex", &lumiera_mutex_section_, \ + NOBUG_RESOURCE_RECURSIVE, lumiera_mutex_section_.rh); \ + if (pthread_mutex_lock (&(mtx)->mutex)) LUMIERA_DIE (MUTEX_LOCK); \ + }); \ + lumiera_mutex_section_.mutex; \ + ({ \ + if (lumiera_mutex_section_.mutex) \ + { \ + pthread_mutex_unlock (&lumiera_mutex_section_.mutex->mutex); \ + lumiera_mutex_section_.mutex = NULL; \ + RESOURCE_LEAVE(nobugflag, lumiera_mutex_section_.rh); \ + } \ })) From 072ea6035299db3160ea411c5f6b64aa2580b0ac Mon Sep 17 00:00:00 2001 From: Christian Thaeter Date: Wed, 24 Dec 2008 03:59:08 +0100 Subject: [PATCH 058/214] Fix: use implicit nobug flag for releasing needs new NoBug as well, I should check my code before pushing it to master --- src/lib/condition.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/lib/condition.h b/src/lib/condition.h index 6e68409bd..328d07c49 100644 --- a/src/lib/condition.h +++ b/src/lib/condition.h @@ -57,7 +57,7 @@ LUMIERA_ERROR_DECLARE (CONDITION_DESTROY); }); \ lumiera_condition_section_.condition; \ ({ \ - LUMIERA_CONDITION_UNLOCK(nobugflag) \ + LUMIERA_CONDITION_UNLOCK \ })) @@ -68,12 +68,12 @@ LUMIERA_ERROR_DECLARE (CONDITION_DESTROY); * got unlocked. * @param nobugflag NoBug flag used to log actions on the condition */ -#define LUMIERA_CONDITION_UNLOCK \ - if (lumiera_condition_section_.condition) \ - { \ - pthread_mutex_unlock (&lumiera_condition_section_.condition->mutex); \ - lumiera_condition_section_.condition = NULL; \ - RESOURCE_LEAVE(nobugflag, lumiera_condition_section_.rh); \ +#define LUMIERA_CONDITION_UNLOCK \ + if (lumiera_condition_section_.condition) \ + { \ + pthread_mutex_unlock (&lumiera_condition_section_.condition->mutex); \ + lumiera_condition_section_.condition = NULL; \ + NOBUG_RESOURCE_LEAVE_RAW(lumiera_condition_section_.flag, lumiera_condition_section_.rh); \ } From 1ff7f0c656d389fc5705e263fdcb7caad31763c0 Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Wed, 24 Dec 2008 23:23:23 +0100 Subject: [PATCH 059/214] Refactoring II: encapsulate the variants probvieded by the backend as base classes --- src/lib/sync.hpp | 116 +++++++++++++++++++++++++++++++++-------------- 1 file changed, 82 insertions(+), 34 deletions(-) diff --git a/src/lib/sync.hpp b/src/lib/sync.hpp index 7968b0df7..4e295909a 100644 --- a/src/lib/sync.hpp +++ b/src/lib/sync.hpp @@ -60,55 +60,105 @@ namespace lib { /** Helpers and building blocks for Monitor based synchronisation */ namespace sync { - class Timeout; - - class RecMutex + + struct Wrapped_LumieraExcMutex + : public lumiera_mutex + { + protected: + Wrapped_LumieraExcMutex() { lumiera_mutex_init (this, "Obj.Monitor ExclMutex", &NOBUG_FLAG(sync)); } + ~Wrapped_LumieraExcMutex() { lumiera_mutex_destroy (this, &NOBUG_FLAG(sync)); } + + //------------------Resource-Tracking------ + void __may_block() { TODO ("Record we may block on mutex"); } + void __enter() { TODO ("Record we successfully acquired the mutex"); } + void __leave() { TODO ("Record we are releasing the mutex"); } + }; + + + struct Wrapped_LumieraRecMutex + : public lumiera_mutex + { + protected: + Wrapped_LumieraRecMutex() { lumiera_recmutex_init (this, "Obj.Monitor ExclMutex", &NOBUG_FLAG(sync)); } + ~Wrapped_LumieraRecMutex() { lumiera_mutex_destroy (this, &NOBUG_FLAG(sync)); } + + //------------------Resource-Tracking------ + void __may_block() { TODO ("Record we may block on mutex"); } + void __enter() { TODO ("Record we successfully acquired the mutex"); } + void __leave() { TODO ("Record we are releasing the mutex"); } + }; + + + struct Wrapped_LumieraExcCond + : public lumiera_condition + { + protected: + Wrapped_LumieraExcCond() { lumiera_condition_init (this, "Obj.Monitor Condition", &NOBUG_FLAG(sync) ); } + ~Wrapped_LumieraExcCond() { lumiera_condition_destroy (this, &NOBUG_FLAG(sync) ); } + + //------------------Resource-Tracking------ + void __may_block() { TODO ("Record we may block on mutex"); } + void __enter() { TODO ("Record we successfully acquired the mutex"); } + void __leave() { TODO ("Record we are releasing the mutex"); } + }; + + + struct Wrapped_LumieraRecCond + : public lumiera_condition + { + protected: + Wrapped_LumieraRecCond() { lumiera_condition_init (this, "Obj.Monitor Condition", &NOBUG_FLAG(sync) ); } ////////TODO + ~Wrapped_LumieraRecCond() { lumiera_condition_destroy (this, &NOBUG_FLAG(sync) ); } + + //------------------Resource-Tracking------ + void __may_block() { TODO ("Record we may block on mutex"); } + void __enter() { TODO ("Record we successfully acquired the mutex"); } + void __leave() { TODO ("Record we are releasing the mutex"); } + }; + + + template + class Mutex + : protected MTX { - lumiera_mutex mtx_; - - pthread_mutex_t* get () { return &mtx_.mutex; } - friend class Condition; - public: - RecMutex() { lumiera_recmutex_init (&mtx_, "Obj.Monitor RecMutex", &NOBUG_FLAG(sync)); } - ~RecMutex() { lumiera_mutex_destroy (&mtx_, &NOBUG_FLAG(sync)); } - void acquire() { - TODO ("Record we may block on mutex"); + __may_block(); - if (pthread_mutex_lock (get())) - throw lumiera::error::State("Mutex acquire failed."); ///////TODO capture the error-code - - TODO ("Record we successfully acquired the mutex"); + if (pthread_mutex_lock (&mutex)) + throw lumiera::error::State("Mutex acquire failed."); ///////TODO capture the error-code + + __enter(); } void release() { - TODO ("Record we are releasing the mutex"); - pthread_mutex_unlock (get()); + __leave(); + + pthread_mutex_unlock (&mutex); } }; + class Timeout; + + + template class Condition + : public Mutex { - lumiera_condition cond_; - public: - Condition() { lumiera_condition_init (&cond_, "Obj.Monitor Condition", &NOBUG_FLAG(sync) ); } - ~Condition() { lumiera_condition_destroy (&cond_, &NOBUG_FLAG(sync) ); } - void signal (bool wakeAll=false) { if (wakeAll) - pthread_cond_broadcast (&cond_.cond); + pthread_cond_broadcast (&cond); else - pthread_cond_signal (&cond_.cond); + pthread_cond_signal (&cond); } @@ -119,9 +169,9 @@ namespace lib { int err=0; while (!predicate() && !err) if (waitEndTime) - err = pthread_cond_timedwait (&cond_.cond, mtx.get(), &waitEndTime); + err = pthread_cond_timedwait (&cond, &mutex, &waitEndTime); else - err = pthread_cond_wait (&cond_.cond, mtx.get()); + err = pthread_cond_wait (&cond, &mutex); if (!err) return true; if (ETIMEDOUT==err) return false; @@ -164,10 +214,8 @@ namespace lib { typedef volatile bool& Flag; class Monitor + : Condition /////////TODO: to be refactored. This is just one example, using the non-recursive condition { - RecMutex mtx_; - Condition cond_; - Timeout timeout_; //////TODO my intention is to make two variants of the monitor, where the simple one leaves out the condition part @@ -176,10 +224,10 @@ namespace lib { Monitor() {} ~Monitor() {} - void acquireLock() { mtx_.acquire(); } - void releaseLock() { mtx_.release(); } + void acquireLock() { acquire(); } + void releaseLock() { release(); } - void signal(bool a){ cond_.signal(a);} + void signal(bool a){ signal(a); } inline bool wait (Flag, ulong); inline void setTimeout(ulong); @@ -211,7 +259,7 @@ namespace lib { Monitor::isTimedWait () {return (timeout_);} - } // namespace sync + } // namespace sync (helpers and building blocks) From 54e88e691499eb71fc60cb2ac2dd9a131c6aa5ad Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Fri, 26 Dec 2008 01:50:32 +0100 Subject: [PATCH 060/214] Refactoring III: Recursive/Nonrecursive and Waitable as policy classes pass test again --- src/lib/allocationcluster.cpp | 12 +- src/lib/allocationcluster.hpp | 2 +- src/lib/singletonpolicies.hpp | 2 +- src/lib/sync.hpp | 137 +++++++++++----------- src/lib/visitordispatcher.hpp | 4 +- src/proc/assetmanager.cpp | 2 +- src/proc/mobject/session/defsregistry.hpp | 2 +- tests/lib/sync-locking-test.cpp | 2 +- tests/lib/sync-waiting-test.cpp | 2 +- 9 files changed, 82 insertions(+), 83 deletions(-) diff --git a/src/lib/allocationcluster.cpp b/src/lib/allocationcluster.cpp index b5eb022ef..4dafb7d48 100644 --- a/src/lib/allocationcluster.cpp +++ b/src/lib/allocationcluster.cpp @@ -81,7 +81,7 @@ namespace lib { void AllocationCluster::MemoryManager::reset (TypeInfo info) { - Sync::ClassLock guard(); + Sync<>::ClassLock guard(); if (0 < mem_.size()) purge(); type_ = info; @@ -96,7 +96,7 @@ namespace lib { void AllocationCluster::MemoryManager::purge() { - Sync::ClassLock guard(); + Sync<>::ClassLock guard(); REQUIRE (type_.killIt, "we need a deleter function"); REQUIRE (0 < type_.allocSize, "allocation size unknown"); @@ -120,7 +120,7 @@ namespace lib { inline void* AllocationCluster::MemoryManager::allocate() { - Sync::ClassLock guard(); + Sync<>::ClassLock guard(); REQUIRE (0 < type_.allocSize); REQUIRE (top_ <= mem_.size()); @@ -140,7 +140,7 @@ namespace lib { inline void AllocationCluster::MemoryManager::commit (void* pendingAlloc) { - Sync::ClassLock guard(); + Sync<>::ClassLock guard(); REQUIRE (pendingAlloc); ASSERT (top_ < mem_.size()); @@ -175,7 +175,7 @@ namespace lib { { try { - Sync::ClassLock guard(); + Sync<>::ClassLock guard(); TRACE (memory, "shutting down AllocationCluster"); for (size_t i = typeHandlers_.size(); 0 < i; --i) @@ -214,7 +214,7 @@ namespace lib { ASSERT (0 < slot); { - Sync::ClassLock guard(); /////TODO: decide tradeoff: lock just the instance, or lock the AllocationCluster class? + Sync<>::ClassLock guard(); /////TODO: decide tradeoff: lock just the instance, or lock the AllocationCluster class? if (slot > typeHandlers_.size()) typeHandlers_.resize(slot); diff --git a/src/lib/allocationcluster.hpp b/src/lib/allocationcluster.hpp index 1e63732cc..51200e740 100644 --- a/src/lib/allocationcluster.hpp +++ b/src/lib/allocationcluster.hpp @@ -222,7 +222,7 @@ namespace lib { static TypeInfo setup() { - Sync::ClassLock guard(); + Sync<>::ClassLock guard(); if (!id_) id_= ++maxTypeIDs; diff --git a/src/lib/singletonpolicies.hpp b/src/lib/singletonpolicies.hpp index d0bade0e1..83c76f5ca 100644 --- a/src/lib/singletonpolicies.hpp +++ b/src/lib/singletonpolicies.hpp @@ -139,7 +139,7 @@ namespace lumiera struct Multithreaded { typedef volatile S VolatileType; - typedef lib::Sync::ClassLock Lock; + typedef lib::Sync<>::ClassLock Lock; }; diff --git a/src/lib/sync.hpp b/src/lib/sync.hpp index 4e295909a..b0a9df32a 100644 --- a/src/lib/sync.hpp +++ b/src/lib/sync.hpp @@ -121,6 +121,12 @@ namespace lib { class Mutex : protected MTX { + protected: + using MTX::mutex; + using MTX::__may_block; + using MTX::__enter; + using MTX::__leave; + public: void acquire() @@ -151,6 +157,10 @@ namespace lib { class Condition : public Mutex { + protected: + using CDX::cond; + using CDX::mutex; + public: void signal (bool wakeAll=false) @@ -162,9 +172,9 @@ namespace lib { } - template + template bool - wait (BF& predicate, MTX& mtx, Timeout& waitEndTime) + wait (BF& predicate, Timeout& waitEndTime) { int err=0; while (!predicate() && !err) @@ -210,32 +220,8 @@ namespace lib { operator bool() { return 0 != tv_sec; } // allows if (timeout_).... }; - typedef volatile bool& Flag; - class Monitor - : Condition /////////TODO: to be refactored. This is just one example, using the non-recursive condition - { - Timeout timeout_; - - //////TODO my intention is to make two variants of the monitor, where the simple one leaves out the condition part - - public: - Monitor() {} - ~Monitor() {} - - void acquireLock() { acquire(); } - void releaseLock() { release(); } - - void signal(bool a){ signal(a); } - - inline bool wait (Flag, ulong); - inline void setTimeout(ulong); - inline bool isTimedWait(); - }; - - - struct BoolFlagPredicate { Flag flag_; @@ -244,25 +230,48 @@ namespace lib { bool operator() () { return flag_; } }; + + template + class Monitor + : IMPL + { + Timeout timeout_; + + public: + Monitor() {} + ~Monitor() {} + + void acquireLock() { IMPL::acquire(); } + void releaseLock() { IMPL::release(); } + + void signal(bool a){ IMPL::signal(a); } + + bool wait (Flag flag, ulong timedwait=0) + { + BoolFlagPredicate checkFlag(flag); + return IMPL::wait(checkFlag, timeout_.setOffset(timedwait)); + } + + void setTimeout(ulong relative) {timeout_.setOffset(relative);} + bool isTimedWait() {return (timeout_);} + }; - bool - Monitor::wait (Flag flag, ulong timedwait) - { - BoolFlagPredicate checkFlag(flag); - return cond_.wait(checkFlag, mtx_, timeout_.setOffset(timedwait)); - } - - void - Monitor::setTimeout (ulong relative) {timeout_.setOffset(relative);} - - bool - Monitor::isTimedWait () {return (timeout_);} + typedef Mutex NonrecursiveLock_NoWait; + typedef Mutex RecursiveLock_NoWait; + typedef Condition NonrecursiveLock_Waitable; + typedef Condition RecursiveLock_Waitable; } // namespace sync (helpers and building blocks) + using sync::NonrecursiveLock_NoWait; + using sync::NonrecursiveLock_Waitable; + using sync::RecursiveLock_NoWait; + using sync::RecursiveLock_Waitable; + + /** * Facility for monitor object based locking. * To be attached either on a per class base or per object base. @@ -274,18 +283,33 @@ namespace lib { * * @todo actually implement this facility using the Lumiera backend. */ + template struct Sync { - typedef sync::Monitor Monitor; - + typedef sync::Monitor Monitor; Monitor objectMonitor_; - /////////////////////////////////////////////////////////////////////////TODO: factor out the recursive/non-recursive mutex case as policy... + static Monitor& + getMonitor(Sync* forThis) + { + REQUIRE (forThis); + return forThis->objectMonitor_; + } template - static inline Monitor& getMonitor(); - - static inline Monitor& getMonitor(Sync* forThis); + static Monitor& + getMonitor() + { + //TODO: a rather obscure race condition is hidden here: + //TODO: depending on the build order, the dtor of this static variable may be called, while another thread is still holding an ClassLock. + //TODO: An possible solution would be to use an shared_ptr to the Monitor in case of a ClassLock and to protect access with another Mutex. + //TODO. But I am really questioning if we can't ignore this case and state: "don't hold a ClassLock when your code maybe still running in shutdown phase!" + //TODO: probably best Idea is to detect this situation in DEBUG or ALPHA mode + + static scoped_ptr classMonitor_ (0); + if (!classMonitor_) classMonitor_.reset (new Monitor ()); + return *classMonitor_; + } class Lock @@ -316,31 +340,6 @@ namespace lib { }; - - - - - Sync::Monitor& - Sync::getMonitor(Sync* forThis) - { - REQUIRE (forThis); - return forThis->objectMonitor_; - } - - template - Sync::Monitor& - Sync::getMonitor() - { - //TODO: a rather obscure race condition is hidden here: - //TODO: depending on the build order, the dtor of this static variable may be called, while another thread is still holding an ClassLock. - //TODO: An possible solution would be to use an shared_ptr to the Monitor in case of a ClassLock and to protect access with another Mutex. - //TODO. But I am really questioning if we can't ignore this case and state: "don't hold a ClassLock when your code maybe still running in shutdown phase!" - //TODO: probably best Idea is to detect this situation in DEBUG or ALPHA mode - - static scoped_ptr classMonitor_ (0); - if (!classMonitor_) classMonitor_.reset (new Monitor ()); - return *classMonitor_; - } } // namespace lumiera diff --git a/src/lib/visitordispatcher.hpp b/src/lib/visitordispatcher.hpp index 7977d7003..4c9145716 100644 --- a/src/lib/visitordispatcher.hpp +++ b/src/lib/visitordispatcher.hpp @@ -62,7 +62,7 @@ namespace lumiera { static void generateID (size_t& id) { - Sync::ClassLock guard(); + Sync<>::ClassLock guard(); if (!id) id = ++lastRegisteredID; } @@ -138,7 +138,7 @@ namespace lumiera { void accomodate (size_t index) { - Sync::ClassLock guard(); + Sync<>::ClassLock guard(); if (index > table_.size()) table_.resize (index); // performance bottleneck?? TODO: measure the real impact! } diff --git a/src/proc/assetmanager.cpp b/src/proc/assetmanager.cpp index 960699189..939162103 100644 --- a/src/proc/assetmanager.cpp +++ b/src/proc/assetmanager.cpp @@ -116,7 +116,7 @@ namespace asset TODO ("check validity of Ident Category"); ID asset_id (getID (idi)); - Sync::ClassLock guard(); + Sync<>::ClassLock guard(); TODO ("handle duplicate Registrations"); P smart_ptr (obj, &destroy); diff --git a/src/proc/mobject/session/defsregistry.hpp b/src/proc/mobject/session/defsregistry.hpp index ad4721b04..f377c3fe6 100644 --- a/src/proc/mobject/session/defsregistry.hpp +++ b/src/proc/mobject/session/defsregistry.hpp @@ -162,7 +162,7 @@ namespace mobject { static void createSlot (Table& table) { - Sync::ClassLock guard(); + Sync<>::ClassLock guard(); if (!index) index = ++maxSlots; if (index > table.size()) diff --git a/tests/lib/sync-locking-test.cpp b/tests/lib/sync-locking-test.cpp index 884b030e7..e246a8083 100644 --- a/tests/lib/sync-locking-test.cpp +++ b/tests/lib/sync-locking-test.cpp @@ -48,7 +48,7 @@ namespace lib { class Victim - : public Sync + : public Sync { volatile long cnt_[NUM_COUNTERS]; volatile uint step_; ///< @note stored as instance variable diff --git a/tests/lib/sync-waiting-test.cpp b/tests/lib/sync-waiting-test.cpp index 3bc087258..1cc8a9398 100644 --- a/tests/lib/sync-waiting-test.cpp +++ b/tests/lib/sync-waiting-test.cpp @@ -66,7 +66,7 @@ namespace lib { class SyncOnBool : public Token, - public Sync + public Sync { bool got_new_data_; From eaedab90ea5635dd93d2c5d1707015f7d1c628de Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Fri, 26 Dec 2008 03:47:12 +0100 Subject: [PATCH 061/214] Refactoring IV: move the (still problematic) ClassLock out of the Sync compound (no semantic change, but better notation) --- src/lib/allocationcluster.cpp | 12 +++--- src/lib/allocationcluster.hpp | 2 +- src/lib/scopedholder.hpp | 2 +- src/lib/singletonpolicies.hpp | 10 ++--- src/lib/sync.hpp | 51 +++++++++++++---------- src/lib/visitordispatcher.hpp | 6 +-- src/proc/mobject/session/defsregistry.hpp | 4 +- 7 files changed, 47 insertions(+), 40 deletions(-) diff --git a/src/lib/allocationcluster.cpp b/src/lib/allocationcluster.cpp index 4dafb7d48..7e13e1538 100644 --- a/src/lib/allocationcluster.cpp +++ b/src/lib/allocationcluster.cpp @@ -81,7 +81,7 @@ namespace lib { void AllocationCluster::MemoryManager::reset (TypeInfo info) { - Sync<>::ClassLock guard(); + ClassLock guard(); if (0 < mem_.size()) purge(); type_ = info; @@ -96,7 +96,7 @@ namespace lib { void AllocationCluster::MemoryManager::purge() { - Sync<>::ClassLock guard(); + ClassLock guard(); REQUIRE (type_.killIt, "we need a deleter function"); REQUIRE (0 < type_.allocSize, "allocation size unknown"); @@ -120,7 +120,7 @@ namespace lib { inline void* AllocationCluster::MemoryManager::allocate() { - Sync<>::ClassLock guard(); + ClassLock guard(); REQUIRE (0 < type_.allocSize); REQUIRE (top_ <= mem_.size()); @@ -140,7 +140,7 @@ namespace lib { inline void AllocationCluster::MemoryManager::commit (void* pendingAlloc) { - Sync<>::ClassLock guard(); + ClassLock guard(); REQUIRE (pendingAlloc); ASSERT (top_ < mem_.size()); @@ -175,7 +175,7 @@ namespace lib { { try { - Sync<>::ClassLock guard(); + ClassLock guard(); TRACE (memory, "shutting down AllocationCluster"); for (size_t i = typeHandlers_.size(); 0 < i; --i) @@ -214,7 +214,7 @@ namespace lib { ASSERT (0 < slot); { - Sync<>::ClassLock guard(); /////TODO: decide tradeoff: lock just the instance, or lock the AllocationCluster class? + ClassLock guard(); /////TODO: decide tradeoff: lock just the instance, or lock the AllocationCluster class? if (slot > typeHandlers_.size()) typeHandlers_.resize(slot); diff --git a/src/lib/allocationcluster.hpp b/src/lib/allocationcluster.hpp index 51200e740..6b7a4838c 100644 --- a/src/lib/allocationcluster.hpp +++ b/src/lib/allocationcluster.hpp @@ -222,7 +222,7 @@ namespace lib { static TypeInfo setup() { - Sync<>::ClassLock guard(); + ClassLock guard(); if (!id_) id_= ++maxTypeIDs; diff --git a/src/lib/scopedholder.hpp b/src/lib/scopedholder.hpp index 986ba956b..f23bffeaa 100644 --- a/src/lib/scopedholder.hpp +++ b/src/lib/scopedholder.hpp @@ -221,7 +221,7 @@ namespace lib { return created_? &_ThisType::created_ : 0; } - bool operator! () const { return !created_; } + bool operator! () const { return !created_; } friend void diff --git a/src/lib/singletonpolicies.hpp b/src/lib/singletonpolicies.hpp index 83c76f5ca..ce01f6ce7 100644 --- a/src/lib/singletonpolicies.hpp +++ b/src/lib/singletonpolicies.hpp @@ -40,10 +40,10 @@ This code is heavily inspired by #include -namespace lumiera - { - namespace singleton - { +namespace lumiera { + namespace singleton { + + /* === several Policies usable in conjunction with lumiera::Singleton === */ /** @@ -139,7 +139,7 @@ namespace lumiera struct Multithreaded { typedef volatile S VolatileType; - typedef lib::Sync<>::ClassLock Lock; + typedef lib::ClassLock Lock; }; diff --git a/src/lib/sync.hpp b/src/lib/sync.hpp index b0a9df32a..01930506e 100644 --- a/src/lib/sync.hpp +++ b/src/lib/sync.hpp @@ -284,7 +284,7 @@ namespace lib { * @todo actually implement this facility using the Lumiera backend. */ template - struct Sync + class Sync { typedef sync::Monitor Monitor; Monitor objectMonitor_; @@ -296,22 +296,8 @@ namespace lib { return forThis->objectMonitor_; } - template - static Monitor& - getMonitor() - { - //TODO: a rather obscure race condition is hidden here: - //TODO: depending on the build order, the dtor of this static variable may be called, while another thread is still holding an ClassLock. - //TODO: An possible solution would be to use an shared_ptr to the Monitor in case of a ClassLock and to protect access with another Mutex. - //TODO. But I am really questioning if we can't ignore this case and state: "don't hold a ClassLock when your code maybe still running in shutdown phase!" - //TODO: probably best Idea is to detect this situation in DEBUG or ALPHA mode - - static scoped_ptr classMonitor_ (0); - if (!classMonitor_) classMonitor_.reset (new Monitor ()); - return *classMonitor_; - } - + public: class Lock { Monitor& mon_; @@ -332,14 +318,35 @@ namespace lib { }; - template - struct ClassLock : Lock - { - ClassLock() : Lock (getMonitor()) {} - }; - }; + + template + class ClassLock + : public Sync::Lock + { + typedef typename Sync::Lock Lock; + typedef typename Sync::Monitor Monitor; + + + static Monitor& + getMonitor() + { + //TODO: a rather obscure race condition is hidden here: + //TODO: depending on the build order, the dtor of this static variable may be called, while another thread is still holding an ClassLock. + //TODO: An possible solution would be to use an shared_ptr to the Monitor in case of a ClassLock and to protect access with another Mutex. + //TODO. But I am really questioning if we can't ignore this case and state: "don't hold a ClassLock when your code maybe still running in shutdown phase!" + //TODO: probably best Idea is to detect this situation in DEBUG or ALPHA mode + + static scoped_ptr classMonitor_ (0); + if (!classMonitor_) classMonitor_.reset (new Monitor ()); + return *classMonitor_; + } + + + public: + ClassLock() : Lock (getMonitor()) {} + }; } // namespace lumiera diff --git a/src/lib/visitordispatcher.hpp b/src/lib/visitordispatcher.hpp index 4c9145716..59784b398 100644 --- a/src/lib/visitordispatcher.hpp +++ b/src/lib/visitordispatcher.hpp @@ -36,7 +36,7 @@ namespace lumiera { namespace visitor { - using lib::Sync; + using lib::ClassLock; template class Tag; @@ -62,7 +62,7 @@ namespace lumiera { static void generateID (size_t& id) { - Sync<>::ClassLock guard(); + ClassLock guard(); if (!id) id = ++lastRegisteredID; } @@ -138,7 +138,7 @@ namespace lumiera { void accomodate (size_t index) { - Sync<>::ClassLock guard(); + ClassLock guard(); if (index > table_.size()) table_.resize (index); // performance bottleneck?? TODO: measure the real impact! } diff --git a/src/proc/mobject/session/defsregistry.hpp b/src/proc/mobject/session/defsregistry.hpp index f377c3fe6..3fc37e5d7 100644 --- a/src/proc/mobject/session/defsregistry.hpp +++ b/src/proc/mobject/session/defsregistry.hpp @@ -58,7 +58,7 @@ namespace mobject { using lumiera::P; using lumiera::Query; - using lib::Sync; + using lib::ClassLock; using std::tr1::weak_ptr; using std::string; @@ -162,7 +162,7 @@ namespace mobject { static void createSlot (Table& table) { - Sync<>::ClassLock guard(); + ClassLock guard(); if (!index) index = ++maxSlots; if (index > table.size()) From 90150b1350b47a9875fb59ceb6070ba0748accd5 Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Fri, 26 Dec 2008 03:47:49 +0100 Subject: [PATCH 062/214] tie AssetManager locking to the Asset DB impl object --- src/proc/asset/db.hpp | 12 +++++++++--- src/proc/assetmanager.cpp | 8 ++++---- src/proc/assetmanager.hpp | 6 +++--- 3 files changed, 16 insertions(+), 10 deletions(-) diff --git a/src/proc/asset/db.hpp b/src/proc/asset/db.hpp index 136a9e4c9..fedbab7ea 100644 --- a/src/proc/asset/db.hpp +++ b/src/proc/asset/db.hpp @@ -27,6 +27,7 @@ #include "pre_a.hpp" +#include "lib/sync.hpp" #include "proc/asset.hpp" #include "include/error.hpp" @@ -35,11 +36,14 @@ #include -namespace asset - { +namespace asset { + using std::tr1::static_pointer_cast; using std::tr1::dynamic_pointer_cast; + using lib::Sync; + using lib::RecursiveLock_NoWait; + /* ===== hash implementations ===== */ @@ -83,7 +87,9 @@ namespace asset * instances known to the Asset Manager subsystem. * As of 8/2007 implemented by a hashtable. */ - class DB : private boost::noncopyable + class DB + : private boost::noncopyable, + public Sync { IdHashtable table; diff --git a/src/proc/assetmanager.cpp b/src/proc/assetmanager.cpp index 939162103..0aaa26c0e 100644 --- a/src/proc/assetmanager.cpp +++ b/src/proc/assetmanager.cpp @@ -42,8 +42,7 @@ using lumiera::Singleton; using lib::Sync; -namespace asset - { +namespace asset { /** * AssetManager error responses, caused by querying @@ -113,14 +112,15 @@ namespace asset throw(lumiera::error::Invalid) { AssetManager& _aMang (AssetManager::instance()); + DB& registry (_aMang.registry); TODO ("check validity of Ident Category"); ID asset_id (getID (idi)); - Sync<>::ClassLock guard(); + DB::Lock guard(®istry); TODO ("handle duplicate Registrations"); P smart_ptr (obj, &destroy); - _aMang.registry.put (asset_id, smart_ptr); + registry.put (asset_id, smart_ptr); return asset_id; } diff --git a/src/proc/assetmanager.hpp b/src/proc/assetmanager.hpp index 44bb5afc0..30962ed02 100644 --- a/src/proc/assetmanager.hpp +++ b/src/proc/assetmanager.hpp @@ -53,8 +53,7 @@ using std::list; -namespace asset - { +namespace asset { class DB; @@ -62,7 +61,8 @@ namespace asset /** * Facade for the Asset subsystem */ - class AssetManager : private boost::noncopyable + class AssetManager + : private boost::noncopyable { asset::DB & registry; From 2173698e75de20971139a3edc9fcaa8632598fff Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Fri, 26 Dec 2008 04:25:01 +0100 Subject: [PATCH 063/214] splitt off the (somewhat problematic) class locking case into a separate header --- src/lib/allocationcluster.hpp | 2 +- src/lib/singletonpolicies.hpp | 2 +- src/lib/sync-classlock.hpp | 71 +++++++++++++++++++++++ src/lib/sync.hpp | 30 +--------- src/lib/visitordispatcher.hpp | 2 +- src/proc/mobject/session/defsregistry.hpp | 2 +- 6 files changed, 77 insertions(+), 32 deletions(-) create mode 100644 src/lib/sync-classlock.hpp diff --git a/src/lib/allocationcluster.hpp b/src/lib/allocationcluster.hpp index 6b7a4838c..e12ccf174 100644 --- a/src/lib/allocationcluster.hpp +++ b/src/lib/allocationcluster.hpp @@ -52,7 +52,7 @@ #include #include "include/error.hpp" -#include "lib/sync.hpp" +#include "lib/sync-classlock.hpp" #include "lib/scopedholder.hpp" #include "lib/scopedholdertransfer.hpp" diff --git a/src/lib/singletonpolicies.hpp b/src/lib/singletonpolicies.hpp index ce01f6ce7..d66182f6a 100644 --- a/src/lib/singletonpolicies.hpp +++ b/src/lib/singletonpolicies.hpp @@ -34,7 +34,7 @@ This code is heavily inspired by #ifndef LUMIERA_SINGLETONPOLICIES_H #define LUMIERA_SINGLETONPOLICIES_H -#include "lib/sync.hpp" +#include "lib/sync-classlock.hpp" #include "include/error.hpp" #include diff --git a/src/lib/sync-classlock.hpp b/src/lib/sync-classlock.hpp new file mode 100644 index 000000000..991291806 --- /dev/null +++ b/src/lib/sync-classlock.hpp @@ -0,0 +1,71 @@ +/* + SYNC-CLASSLOCK.hpp - special case of object based locking tied directly to a type + + Copyright (C) Lumiera.org + 2008, Christian Thaeter + Hermann Vosseler + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +/** @file sync-classlock.hpp + ** A special implementation of lib::Sync, where the storage of the object monitor + ** is associated directly to a type rather then to a single object instance. While + ** being problematic in conjunction with static startup/shutdown, doing so is sometimes + ** necessary to setup type based dispatcher tables, managing singleton creation etc. + ** + ** @see singletonfactory.hpp usage example + */ + + +#ifndef LIB_SYNC_CLASSLOCK_H +#define LIB_SYNC_CLASSLOCK_H + +#include "lib/sync.hpp" + + +namespace lib { + + template + class ClassLock + : public Sync::Lock + { + typedef typename Sync::Lock Lock; + typedef typename Sync::Monitor Monitor; + + + static Monitor& + getMonitor() + { + //TODO: a rather obscure race condition is hidden here: + //TODO: depending on the build order, the dtor of this static variable may be called, while another thread is still holding an ClassLock. + //TODO: An possible solution would be to use an shared_ptr to the Monitor in case of a ClassLock and to protect access with another Mutex. + //TODO. But I am really questioning if we can't ignore this case and state: "don't hold a ClassLock when your code maybe still running in shutdown phase!" + //TODO: probably best Idea is to detect this situation in DEBUG or ALPHA mode + + static scoped_ptr classMonitor_ (0); + if (!classMonitor_) classMonitor_.reset (new Monitor ()); + return *classMonitor_; + } + + + public: + ClassLock() : Lock (getMonitor()) {} + }; + + +} // namespace lib +#endif diff --git a/src/lib/sync.hpp b/src/lib/sync.hpp index 01930506e..81b2ec019 100644 --- a/src/lib/sync.hpp +++ b/src/lib/sync.hpp @@ -1,5 +1,5 @@ /* - CONCURRENCY.hpp - generic helper for object based locking and synchronisation + SYNC.hpp - generic helper for object based locking and synchronisation Copyright (C) Lumiera.org 2008, Christian Thaeter @@ -320,33 +320,7 @@ namespace lib { }; - - template - class ClassLock - : public Sync::Lock - { - typedef typename Sync::Lock Lock; - typedef typename Sync::Monitor Monitor; - - - static Monitor& - getMonitor() - { - //TODO: a rather obscure race condition is hidden here: - //TODO: depending on the build order, the dtor of this static variable may be called, while another thread is still holding an ClassLock. - //TODO: An possible solution would be to use an shared_ptr to the Monitor in case of a ClassLock and to protect access with another Mutex. - //TODO. But I am really questioning if we can't ignore this case and state: "don't hold a ClassLock when your code maybe still running in shutdown phase!" - //TODO: probably best Idea is to detect this situation in DEBUG or ALPHA mode - - static scoped_ptr classMonitor_ (0); - if (!classMonitor_) classMonitor_.reset (new Monitor ()); - return *classMonitor_; - } - - - public: - ClassLock() : Lock (getMonitor()) {} - }; + } // namespace lumiera diff --git a/src/lib/visitordispatcher.hpp b/src/lib/visitordispatcher.hpp index 59784b398..65b2ecfff 100644 --- a/src/lib/visitordispatcher.hpp +++ b/src/lib/visitordispatcher.hpp @@ -26,7 +26,7 @@ #define LUMIERA_VISITORDISPATCHER_H #include "include/error.hpp" -#include "lib/sync.hpp" +#include "lib/sync-classlock.hpp" #include "lib/singleton.hpp" #include "lib/util.hpp" diff --git a/src/proc/mobject/session/defsregistry.hpp b/src/proc/mobject/session/defsregistry.hpp index 3fc37e5d7..06133b292 100644 --- a/src/proc/mobject/session/defsregistry.hpp +++ b/src/proc/mobject/session/defsregistry.hpp @@ -40,7 +40,7 @@ #define MOBJECT_SESSION_DEFSREGISTRY_H -#include "lib/sync.hpp" +#include "lib/sync-classlock.hpp" #include "lib/query.hpp" #include "lib/util.hpp" #include "lib/p.hpp" From bd2ead37d591f495fc5c94449362c193262a4d97 Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Fri, 26 Dec 2008 05:44:49 +0100 Subject: [PATCH 064/214] Refactoring V: get lifecycle of a class-based monitor correct. --- src/lib/sync-classlock.hpp | 74 ++++++++++++++++++----- tests/40components.tests | 20 +++++-- tests/lib/sync-classlock-test.cpp | 98 +++++++++++++++++++++++++++++++ 3 files changed, 172 insertions(+), 20 deletions(-) create mode 100644 tests/lib/sync-classlock-test.cpp diff --git a/src/lib/sync-classlock.hpp b/src/lib/sync-classlock.hpp index 991291806..2cb37d17a 100644 --- a/src/lib/sync-classlock.hpp +++ b/src/lib/sync-classlock.hpp @@ -27,6 +27,8 @@ ** being problematic in conjunction with static startup/shutdown, doing so is sometimes ** necessary to setup type based dispatcher tables, managing singleton creation etc. ** + ** @note simply using the ClassLock may cause a Monitor object (with a mutex) to be + ** created at static initialisation and destroyed on application shutdown. ** @see singletonfactory.hpp usage example */ @@ -39,31 +41,73 @@ namespace lib { + namespace { // implementation details + + template + struct NiftyHolder + { + static uint accessed_; + static char content_[sizeof(X)]; + + NiftyHolder() + { + if (!accessed_) + new(content_) X(); + ++accessed_; + } + + ~NiftyHolder() + { + --accessed_; + if (0==accessed_) + get().~X(); + } + + X& + get() + { + X* obj = reinterpret_cast (&content_); + ASSERT (obj, "Logic of Schwartz counter broken."); + return *obj; + } + }; + + template + uint NiftyHolder::accessed_; + + template + char NiftyHolder::content_[sizeof(X)]; + + } // (End) implementation details + + + + /** + * A synchronisation protection guard employing a lock scoped + * to the parameter type as a whole, not an individual instance. + * After creating an instance, every other access specifying the same + * type is blocked. + * @warn beware of recursion when using a nonrecursive Mutex + * @see Sync::Lock the usual simple instance-bound variant + */ template class ClassLock : public Sync::Lock { typedef typename Sync::Lock Lock; - typedef typename Sync::Monitor Monitor; + typedef typename sync::Monitor Monitor; - - static Monitor& - getMonitor() + Monitor& + getPerClassMonitor() { - //TODO: a rather obscure race condition is hidden here: - //TODO: depending on the build order, the dtor of this static variable may be called, while another thread is still holding an ClassLock. - //TODO: An possible solution would be to use an shared_ptr to the Monitor in case of a ClassLock and to protect access with another Mutex. - //TODO. But I am really questioning if we can't ignore this case and state: "don't hold a ClassLock when your code maybe still running in shutdown phase!" - //TODO: probably best Idea is to detect this situation in DEBUG or ALPHA mode - - static scoped_ptr classMonitor_ (0); - if (!classMonitor_) classMonitor_.reset (new Monitor ()); - return *classMonitor_; + static NiftyHolder __used_here; + return __used_here.get(); } - public: - ClassLock() : Lock (getMonitor()) {} + ClassLock() : Lock (getPerClassMonitor()) {} + + uint use_count() { return NiftyHolder::accessed_; } }; diff --git a/tests/40components.tests b/tests/40components.tests index c1bf07b0c..ca079d7ef 100644 --- a/tests/40components.tests +++ b/tests/40components.tests @@ -158,11 +158,6 @@ return: 0 END -PLANNED "Multithread Locking by Monitor" ConcurrencyLocking_test < Testgroup=ALL diff --git a/tests/lib/sync-classlock-test.cpp b/tests/lib/sync-classlock-test.cpp new file mode 100644 index 000000000..d53c031ef --- /dev/null +++ b/tests/lib/sync-classlock-test.cpp @@ -0,0 +1,98 @@ +/* + SyncClasslock(Test) - validate the type-based Monitor locking + + Copyright (C) Lumiera.org + 2008, Hermann Vosseler + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +* *****************************************************/ + + +#include "lib/test/run.hpp" +#include "include/error.hpp" + +#include "lib/sync-classlock.hpp" + +//#include + +//using std::cout; +using test::Test; + + +namespace lib { + namespace test { + + namespace { // private test classes and data... + + const uint NUM_INSTANCES = 20; ///< number of probe instances to create + + + /** + * instances of this probe class will be created statically. + * They utilise the class-based locking within ctor and dtor + */ + struct Probe + { + Probe() { ClassLock ctor_lock; } + ~Probe() { ClassLock dtor_lock; } + }; + + + } // (End) test classes and data.... + + + + + + + + + + + /************************************************************************** + * @test check proper handling of class (not instance)-based Monitor locks. + * Because no instance is available in this case, a hidden storage for the + * Monitor object needs to be provided in a way safe for use even in the + * static startup/shutdown phase. This test validates the associated + * refcounting and object creation works as expected. It does \em not + * validate the locking functionality as such. + * + * @see sync.hpp + */ + class SyncClasslock_test : public Test + { + + virtual void + run (Arg) + { + static Probe objs[NUM_INSTANCES]; + + ClassLock get_class_lock; + ASSERT ( 1 == get_class_lock.use_count()); // ClassLock got created exactly once + } + + }; + + + + /** Register this test class... */ + LAUNCHER (SyncClasslock_test, "unit common"); + + + + } // namespace test + +} // namespace lumiera From be8d7644ed14b3f26837fe4234df1a686884c3b9 Mon Sep 17 00:00:00 2001 From: Joel Holdsworth Date: Fri, 26 Dec 2008 18:10:28 +0000 Subject: [PATCH 065/214] Added the MenuButton class for buttons with popup menus --- src/gui/Makefile.am | 2 + src/gui/widgets/menu-button.cpp | 79 ++++++++++++++++++ src/gui/widgets/menu-button.hpp | 90 +++++++++++++++++++++ src/gui/widgets/timeline/timeline-track.cpp | 11 +-- src/gui/widgets/timeline/timeline-track.hpp | 8 +- 5 files changed, 175 insertions(+), 15 deletions(-) create mode 100644 src/gui/widgets/menu-button.cpp create mode 100644 src/gui/widgets/menu-button.hpp diff --git a/src/gui/Makefile.am b/src/gui/Makefile.am index 8468c566e..e7b27e7fc 100644 --- a/src/gui/Makefile.am +++ b/src/gui/Makefile.am @@ -108,6 +108,8 @@ libgui_la_SOURCES = \ $(lumigui_srcdir)/panels/assets-panel.hpp \ $(lumigui_srcdir)/widgets/video-display-widget.cpp \ $(lumigui_srcdir)/widgets/video-display-widget.hpp \ + $(lumigui_srcdir)/widgets/menu-button.cpp \ + $(lumigui_srcdir)/widgets/menu-button.hpp \ $(lumigui_srcdir)/widgets/timeline-widget.cpp \ $(lumigui_srcdir)/widgets/timeline-widget.hpp \ $(lumigui_srcdir)/widgets/timeline/timeline-view-window.cpp \ diff --git a/src/gui/widgets/menu-button.cpp b/src/gui/widgets/menu-button.cpp new file mode 100644 index 000000000..95e8ff306 --- /dev/null +++ b/src/gui/widgets/menu-button.cpp @@ -0,0 +1,79 @@ +/* + timeline-widget.cpp - Implementation of the menu button widget + + Copyright (C) Lumiera.org + 2008, Joel Holdsworth + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +* *****************************************************/ + +#include "menu-button.hpp" + +#include + +using namespace Gtk; +using namespace sigc; + +namespace gui { +namespace widgets { + +MenuButton::MenuButton() : + Button() +{} + +MenuButton::MenuButton(const Gtk::StockID& stock_id) + : Button(stock_id) +{} + +MenuButton::MenuButton(const Glib::ustring& label, bool mnemonic) + : Button(label, mnemonic) +{} + +Gtk::Menu& +MenuButton::get_menu() +{ + return menu; +} + +void +MenuButton::on_pressed() +{ + popup(); +} + +void +MenuButton::popup() +{ + menu.popup( mem_fun(this, &MenuButton::on_menu_position), + 0, gtk_get_current_event_time()); +} + +void +MenuButton::on_menu_position(int& x, int& y, bool& push_in) +{ + Glib::RefPtr window = get_window(); + REQUIRE(window); + + window->get_origin(x, y); + const Allocation allocation = get_allocation(); + x += allocation.get_x(); + y += allocation.get_y() + allocation.get_height(); + + push_in = true; +} + +} // widgets +} // gui diff --git a/src/gui/widgets/menu-button.hpp b/src/gui/widgets/menu-button.hpp new file mode 100644 index 000000000..86f180564 --- /dev/null +++ b/src/gui/widgets/menu-button.hpp @@ -0,0 +1,90 @@ +/* + menu-button.hpp - Declaration of the menu button widget + + Copyright (C) Lumiera.org + 2008, Joel Holdsworth + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ +/** @file timeline-widget.hpp + ** This file contains the definition of timeline widget + */ + +#ifndef MENU_BUTTON_HPP +#define MENU_BUTTON_HPP + +#include + +namespace gui { +namespace widgets { + +/** + * A button that display a menu when clicked on. + **/ +class MenuButton : public Gtk::Button +{ +public: + + /** + * Create an empty button. + * @remarks With an empty button, you can Gtk::Button::add() a widget + * such as a Gtk::Pixmap or Gtk::Box. If you just wish to add a + * Gtk::Label, you may want to use the + * Gtk::MenuButton(const Glib::ustring& label) ctor directly instead. + **/ + MenuButton(); + + /** + * Creates a new Button containing the image and text from a stock + * item. + * @remarks Stock ids have identifiers like Gtk::Stock::OK and + * Gtk::Stock::APPLY. + **/ + MenuButton(const Gtk::StockID& stock_id); + + /** + * Creates a simple Push Button with label. + * @remarks Create a button with the given label inside. You won't be + * able to add a widget in this button since it already has a + * Gtk::Label in it + **/ + MenuButton(const Glib::ustring& label, bool mnemonic=false); + + /** + * Gets the menu which will be displayed when the button is clicked + * on. + * @return Returns a reference to the menu that will be clicked on. + * This reference can be used to populate the menu with items. + **/ + Gtk::Menu& get_menu(); + + void popup(); + +protected: + virtual void on_pressed(); + +private: + void on_menu_position(int& x, int& y, bool& push_in); + +private: + Gtk::Menu menu; +}; + +} // gui +} // widgets + +#endif // MENU_BUTTON_HPP + diff --git a/src/gui/widgets/timeline/timeline-track.cpp b/src/gui/widgets/timeline/timeline-track.cpp index 828598d4a..30315611e 100644 --- a/src/gui/widgets/timeline/timeline-track.cpp +++ b/src/gui/widgets/timeline/timeline-track.cpp @@ -43,8 +43,6 @@ Track::Track(TimelineWidget &timeline_widget) : lockButton(Gtk::StockID("track_unlocked")) { titleMenuButton.set_relief(RELIEF_HALF); - titleMenuButton.signal_pressed().connect( - mem_fun(this, &Track::on_title_menu_button) ); buttonBar.append(enableButton); buttonBar.append(lockButton); @@ -65,7 +63,7 @@ Track::Track(TimelineWidget &timeline_widget) : headerWidget.pack_start(buttonBar, PACK_SHRINK); // Setup the title menu - Menu::MenuList& title_list = titleMenu.items(); + Menu::MenuList& title_list = titleMenuButton.get_menu().items(); title_list.push_back( Menu_Helpers::MenuElem(_("_Name..."), mem_fun(this, &Track::on_remove_track) ) ); @@ -107,13 +105,6 @@ Track::show_header_context_menu(guint button, guint32 time) contextMenu.popup(button, time); } -void -Track::on_title_menu_button() -{ - g_message("Hello"); - titleMenu.popup(0, gtk_get_current_event_time()); -} - void Track::on_remove_track() { diff --git a/src/gui/widgets/timeline/timeline-track.hpp b/src/gui/widgets/timeline/timeline-track.hpp index 0fdd87884..1407e3b94 100644 --- a/src/gui/widgets/timeline/timeline-track.hpp +++ b/src/gui/widgets/timeline/timeline-track.hpp @@ -25,6 +25,7 @@ #include "../../gtk-lumiera.hpp" #include "../../model/track.hpp" +#include "../menu-button.hpp" #include "timeline-header-container.hpp" #ifndef TIMELINE_TRACK_HPP @@ -57,9 +58,8 @@ public: private: - void on_title_menu_button(); - void on_remove_track(); + private: @@ -71,7 +71,7 @@ private: Gtk::VBox headerWidget; - Gtk::Button titleMenuButton; + MenuButton titleMenuButton; Gtk::ToolButton enableButton; Gtk::ToolButton lockButton; @@ -79,8 +79,6 @@ private: Gtk::Entry titleBox; Gtk::Toolbar buttonBar; - Gtk::Menu titleMenu; - Gtk::Menu contextMenu; }; From 58d2f05db49f774ea96a3dcb5bc5c76fb1df34d5 Mon Sep 17 00:00:00 2001 From: Joel Holdsworth Date: Fri, 26 Dec 2008 18:14:45 +0000 Subject: [PATCH 066/214] Added some documentation to menu-bbutton.hpp --- src/gui/widgets/menu-button.hpp | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/gui/widgets/menu-button.hpp b/src/gui/widgets/menu-button.hpp index 86f180564..38c21cdfc 100644 --- a/src/gui/widgets/menu-button.hpp +++ b/src/gui/widgets/menu-button.hpp @@ -71,15 +71,37 @@ public: **/ Gtk::Menu& get_menu(); + /** + * Pops up the menu. + **/ void popup(); protected: + + /** + * An event handler for when the button is pressed. + **/ virtual void on_pressed(); private: + + /** + * A callback function used to determine the correct position for the + * popup menu. + * @param x The x-coordinate to display the menu in root window + * coordinates. + * @param y The y-coordinate to display the menu in root window + * coordinates. + * @param push_in This value is set to true if the menu should be + * pushed in if it collides with the edge of the screen. + **/ void on_menu_position(int& x, int& y, bool& push_in); private: + + /** + * The internal menu object which is the popup menu of this widget. + **/ Gtk::Menu menu; }; From b75e6a982b92a3a8a5d23c3227fac905cf10b86a Mon Sep 17 00:00:00 2001 From: Joel Holdsworth Date: Fri, 26 Dec 2008 18:49:28 +0000 Subject: [PATCH 067/214] Converted to the SequenceName dialog to a generic name chooser dialog: NameChooser --- src/gui/Makefile.am | 4 +-- .../{sequence-name.cpp => name-chooser.cpp} | 27 +++++-------------- .../{sequence-name.hpp => name-chooser.hpp} | 9 ++++--- src/gui/workspace/actions.cpp | 6 ++--- 4 files changed, 16 insertions(+), 30 deletions(-) rename src/gui/dialogs/{sequence-name.cpp => name-chooser.cpp} (76%) rename src/gui/dialogs/{sequence-name.hpp => name-chooser.hpp} (88%) diff --git a/src/gui/Makefile.am b/src/gui/Makefile.am index e7b27e7fc..fd1ecbd84 100644 --- a/src/gui/Makefile.am +++ b/src/gui/Makefile.am @@ -96,8 +96,8 @@ libgui_la_SOURCES = \ $(lumigui_srcdir)/dialogs/render.hpp \ $(lumigui_srcdir)/dialogs/preferences-dialog.cpp \ $(lumigui_srcdir)/dialogs/preferences-dialog.hpp \ - $(lumigui_srcdir)/dialogs/sequence-name.cpp \ - $(lumigui_srcdir)/dialogs/sequence-name.hpp \ + $(lumigui_srcdir)/dialogs/name-chooser.cpp \ + $(lumigui_srcdir)/dialogs/name-chooser.hpp \ $(lumigui_srcdir)/panels/panel.cpp \ $(lumigui_srcdir)/panels/panel.hpp \ $(lumigui_srcdir)/panels/timeline-panel.cpp \ diff --git a/src/gui/dialogs/sequence-name.cpp b/src/gui/dialogs/name-chooser.cpp similarity index 76% rename from src/gui/dialogs/sequence-name.cpp rename to src/gui/dialogs/name-chooser.cpp index 4abaf1841..924361fe6 100644 --- a/src/gui/dialogs/sequence-name.cpp +++ b/src/gui/dialogs/name-chooser.cpp @@ -21,7 +21,7 @@ * *****************************************************/ #include "../gtk-lumiera.hpp" -#include "sequence-name.hpp" +#include "name-chooser.hpp" #include "dialog.hpp" using namespace Gtk; @@ -30,28 +30,13 @@ using namespace Glib; namespace gui { namespace dialogs { -SequenceName::SequenceName(Window &parent, Action action, - ustring default_title) : - Dialog::Dialog("", parent, true), +NameChooser::NameChooser(Window &parent, Glib::ustring title, + Glib::ustring default_name) : + Dialog::Dialog(title, parent, true), caption(_("Name:")) { - // Choose the dialog title - ustring title; - - switch(action) - { - case AddSequence: title = _("Add Sequence"); break; - case RenameSequence: title = _("Rename Sequence"); break; - - default: - ASSERT(0); // An invalid action value was supplied - break; - } - - set_title(title); - // Add the controls - name.set_text(default_title); + name.set_text(default_name); name.set_activates_default(); hBox.pack_start(caption); @@ -75,7 +60,7 @@ SequenceName::SequenceName(Window &parent, Action action, show_all_children(); } -const Glib::ustring SequenceName::get_name() const +const Glib::ustring NameChooser::get_name() const { return name.get_text(); } diff --git a/src/gui/dialogs/sequence-name.hpp b/src/gui/dialogs/name-chooser.hpp similarity index 88% rename from src/gui/dialogs/sequence-name.hpp rename to src/gui/dialogs/name-chooser.hpp index d5f85d2b4..7cc735bdd 100644 --- a/src/gui/dialogs/sequence-name.hpp +++ b/src/gui/dialogs/name-chooser.hpp @@ -33,9 +33,9 @@ namespace gui { namespace dialogs { /** - * The defintion of sequence name dialog class + * The defintion of the name chooser dialog class */ -class SequenceName : public Gtk::Dialog +class NameChooser : public Gtk::Dialog { public: @@ -46,8 +46,9 @@ public: }; public: - SequenceName(Gtk::Window &parent, SequenceName::Action action, - Glib::ustring default_title); + + NameChooser(Gtk::Window &parent, Glib::ustring title, + Glib::ustring default_name); const Glib::ustring get_name() const; diff --git a/src/gui/workspace/actions.cpp b/src/gui/workspace/actions.cpp index fcf81dab4..0ef837707 100644 --- a/src/gui/workspace/actions.cpp +++ b/src/gui/workspace/actions.cpp @@ -25,7 +25,7 @@ #include "../dialogs/render.hpp" #include "../dialogs/preferences-dialog.hpp" -#include "../dialogs/sequence-name.hpp" +#include "../dialogs/name-chooser.hpp" #include "../model/project.hpp" @@ -185,8 +185,8 @@ Actions::on_menu_view_viewer() void Actions::on_menu_sequence_add() { - dialogs::SequenceName dialog(workspaceWindow, - dialogs::SequenceName::AddSequence, "New Sequence"); + dialogs::NameChooser dialog(workspaceWindow, + _("Add Sequence"), _("New Sequence")); if(dialog.run() == RESPONSE_OK) workspaceWindow.get_project()->add_new_sequence(dialog.get_name()); } From 33afd58b8e463d3d17cf0f876e736fa93777b3aa Mon Sep 17 00:00:00 2001 From: Joel Holdsworth Date: Fri, 26 Dec 2008 18:58:29 +0000 Subject: [PATCH 068/214] Converted all ASSERTs to REQUIREs --- src/gui/dialogs/name-chooser.cpp | 2 +- src/gui/dialogs/render.cpp | 2 +- src/gui/output/gdkdisplayer.cpp | 8 ++++---- src/gui/output/xvdisplayer.cpp | 2 +- src/gui/panels/timeline-panel.cpp | 6 +++--- src/gui/widgets/timeline-widget.cpp | 8 ++++---- src/gui/widgets/timeline/timeline-body.cpp | 4 ++-- .../widgets/timeline/timeline-header-container.cpp | 12 ++++++------ src/gui/widgets/timeline/timeline-track.cpp | 4 ++-- src/gui/workspace/workspace-window.cpp | 4 ++-- 10 files changed, 26 insertions(+), 26 deletions(-) diff --git a/src/gui/dialogs/name-chooser.cpp b/src/gui/dialogs/name-chooser.cpp index 924361fe6..0017b8bb7 100644 --- a/src/gui/dialogs/name-chooser.cpp +++ b/src/gui/dialogs/name-chooser.cpp @@ -44,7 +44,7 @@ NameChooser::NameChooser(Window &parent, Glib::ustring title, hBox.set_spacing(BoxSpacing); VBox* const v_box = get_vbox(); - ASSERT(v_box != NULL); + REQUIRE(v_box != NULL); v_box->pack_start(hBox); // Configure the dialog diff --git a/src/gui/dialogs/render.cpp b/src/gui/dialogs/render.cpp index 5afa00f76..91bdbaf67 100644 --- a/src/gui/dialogs/render.cpp +++ b/src/gui/dialogs/render.cpp @@ -41,7 +41,7 @@ Render::Render(Window &parent) : videoFrame(_("Video")) { VBox *v_box = get_vbox(); - ASSERT(v_box != NULL); + REQUIRE(v_box != NULL); // The Output File Row outputFileHBox.pack_start(outputFileLabel, PACK_SHRINK); diff --git a/src/gui/output/gdkdisplayer.cpp b/src/gui/output/gdkdisplayer.cpp index ffe6b81e3..0f83ceac4 100644 --- a/src/gui/output/gdkdisplayer.cpp +++ b/src/gui/output/gdkdisplayer.cpp @@ -61,17 +61,17 @@ GdkDisplayer::put( void *image ) video_x, video_y, video_width, video_height ); GdkWindow *window = drawingArea->get_window()->gobj(); - ASSERT(window != NULL); + REQUIRE(window != NULL); GdkGC *gc = gdk_gc_new( window ); - ASSERT(gc != NULL); + REQUIRE(gc != NULL); GdkPixbuf *pixbuf = gdk_pixbuf_new_from_data( (const guchar*)image, GDK_COLORSPACE_RGB, FALSE, 8, preferredWidth(), preferredHeight(), preferredWidth() * 3, NULL, NULL ); - ASSERT(pixbuf != NULL); + REQUIRE(pixbuf != NULL); GdkPixbuf *scaled_image = gdk_pixbuf_scale_simple( pixbuf, video_width, video_height, GDK_INTERP_NEAREST ); - ASSERT(scaled_image != NULL); + REQUIRE(scaled_image != NULL); gdk_draw_pixbuf( window, gc, scaled_image, 0, 0, video_x, video_y, -1, -1, GDK_RGB_DITHER_NORMAL, 0, 0 ); diff --git a/src/gui/output/xvdisplayer.cpp b/src/gui/output/xvdisplayer.cpp index db3d2b25e..13a692a40 100644 --- a/src/gui/output/xvdisplayer.cpp +++ b/src/gui/output/xvdisplayer.cpp @@ -201,7 +201,7 @@ void XvDisplayer::put( void *image ) { REQUIRE(image != NULL); - ASSERT(drawingArea != NULL); + REQUIRE(drawingArea != NULL); if(xvImage != NULL) { diff --git a/src/gui/panels/timeline-panel.cpp b/src/gui/panels/timeline-panel.cpp index 9572ae8e6..03cdc8e2f 100644 --- a/src/gui/panels/timeline-panel.cpp +++ b/src/gui/panels/timeline-panel.cpp @@ -160,7 +160,7 @@ void TimelinePanel::on_zoom_in() { TimelineWidget *const widget = get_current_page(); - ASSERT(widget != NULL); + REQUIRE(widget != NULL); widget->get_view_window().zoom_view(ZoomToolSteps); update_zoom_buttons(); @@ -170,7 +170,7 @@ void TimelinePanel::on_zoom_out() { TimelineWidget *const widget = get_current_page(); - ASSERT(widget != NULL); + REQUIRE(widget != NULL); widget->get_view_window().zoom_view(-ZoomToolSteps); update_zoom_buttons(); @@ -201,7 +201,7 @@ TimelinePanel::on_playback_period_drag_released() // real backend TimelineWidget *const widget = get_current_page(); - ASSERT(widget != NULL); + REQUIRE(widget != NULL); widget->set_playback_point(widget->get_playback_period_start()); //----- END TEST CODE diff --git a/src/gui/widgets/timeline-widget.cpp b/src/gui/widgets/timeline-widget.cpp index 7798fba76..fa85d6a2d 100644 --- a/src/gui/widgets/timeline-widget.cpp +++ b/src/gui/widgets/timeline-widget.cpp @@ -296,7 +296,7 @@ TimelineWidget::update_tracks() create_timeline_tracks(); // Update the header container - ASSERT(headerContainer != NULL); + REQUIRE(headerContainer != NULL); headerContainer->show_all_children(); headerContainer->update_headers(); @@ -308,7 +308,7 @@ TimelineWidget::update_tracks() BOOST_FOREACH(shared_ptr track, sequence->get_child_tracks()) { - ASSERT(track); + REQUIRE(track); totalHeight += measure_branch_height(track); } } @@ -456,7 +456,7 @@ TimelineWidget::lookup_model_track( void TimelineWidget::update_scroll() { - ASSERT(body != NULL); + REQUIRE(body != NULL); const Allocation body_allocation = body->get_allocation(); //----- Horizontal Scroll ------// @@ -511,7 +511,7 @@ TimelineWidget::measure_branch_height( BOOST_FOREACH( shared_ptr child, model_track->get_child_tracks() ) { - ASSERT(child != NULL); + REQUIRE(child); height += measure_branch_height(child); } diff --git a/src/gui/widgets/timeline/timeline-body.cpp b/src/gui/widgets/timeline/timeline-body.cpp index b1d1eb6da..7e8125cac 100644 --- a/src/gui/widgets/timeline/timeline-body.cpp +++ b/src/gui/widgets/timeline/timeline-body.cpp @@ -303,7 +303,7 @@ TimelineBody::draw_track_recursive(Cairo::RefPtr cr, lookup_timeline_track(model_track); const int height = timeline_track->get_height(); - ASSERT(height >= 0); + REQUIRE(height >= 0); // Draw the track background cr->rectangle(0, 0, view_width, height); @@ -453,7 +453,7 @@ shared_ptr TimelineBody::track_from_branch( lookup_timeline_track(model_track); const int height = timeline_track->get_height(); - ASSERT(height >= 0); + REQUIRE(height >= 0); // Does the point fall in this track? if(offset <= y && y < offset + height) diff --git a/src/gui/widgets/timeline/timeline-header-container.cpp b/src/gui/widgets/timeline/timeline-header-container.cpp index 506eb0316..d9c15fc90 100644 --- a/src/gui/widgets/timeline/timeline-header-container.cpp +++ b/src/gui/widgets/timeline/timeline-header-container.cpp @@ -248,7 +248,7 @@ TimelineHeaderContainer::forall_vfunc(gboolean /* include_internals */, BOOST_FOREACH( shared_ptr track, get_tracks() ) { - ASSERT(track != NULL); + REQUIRE(track); forall_vfunc_recursive(track, callback, callback_data); } } @@ -275,7 +275,7 @@ TimelineHeaderContainer::on_expose_event(GdkEventExpose *event) BOOST_FOREACH( shared_ptr model_track, get_tracks() ) { - ASSERT(model_track != NULL); + REQUIRE(model_track); draw_header_decoration(model_track, Gdk::Rectangle(0, 0, @@ -354,7 +354,7 @@ TimelineHeaderContainer::layout_headers_recursive( offset, // y max( header_width - indent, 0 ), // width track_height); // height - ASSERT(header_box.get_height() >= 0); + REQUIRE(header_box.get_height() >= 0); // Cache the bounding box headerBoxes[timeline_track] = header_box; @@ -448,14 +448,14 @@ TimelineHeaderContainer::draw_header_decoration( REQUIRE(clip_rect.get_height() > 0); Glib::RefPtr