[Aptitude-svn-commit] r4041 - in branches/aptitude-0.3/aptitude: . src

Daniel Burrows dburrows at costa.debian.org
Fri Sep 2 23:57:02 UTC 2005


Author: dburrows
Date: Fri Sep  2 23:56:59 2005
New Revision: 4041

Added:
   branches/aptitude-0.3/aptitude/src/download_thread.cc
   branches/aptitude-0.3/aptitude/src/download_thread.h
Modified:
   branches/aptitude-0.3/aptitude/ChangeLog
   branches/aptitude-0.3/aptitude/src/Makefile.am
Log:
Write harness code for running downloads in the background.

Modified: branches/aptitude-0.3/aptitude/ChangeLog
==============================================================================
--- branches/aptitude-0.3/aptitude/ChangeLog	(original)
+++ branches/aptitude-0.3/aptitude/ChangeLog	Fri Sep  2 23:56:59 2005
@@ -1,5 +1,9 @@
 2005-09-02  Daniel Burrows  <dburrows at debian.org>
 
+	* src/Makefile.am, src/download_thread.cc, src/download_thread.h:
+
+	  Write harness code for running downloads in the background.
+
 	* src/generic/threads.h:
 
 	  Fix some silly compilation errors; make all broken-out box

Modified: branches/aptitude-0.3/aptitude/src/Makefile.am
==============================================================================
--- branches/aptitude-0.3/aptitude/src/Makefile.am	(original)
+++ branches/aptitude-0.3/aptitude/src/Makefile.am	Fri Sep  2 23:56:59 2005
@@ -37,6 +37,8 @@
 	download_list.cc \
 	download_screen.h\
 	download_screen.cc\
+	download_thread.h\
+	download_thread.cc\
 	download_manager.h\
 	download_manager.cc\
 	edit_pkg_hier.h	\

Added: branches/aptitude-0.3/aptitude/src/download_thread.cc
==============================================================================
--- (empty file)
+++ branches/aptitude-0.3/aptitude/src/download_thread.cc	Fri Sep  2 23:56:59 2005
@@ -0,0 +1,160 @@
+// download_thread.cc
+//
+//   Copyright (C) 2005 Daniel Burrows
+//
+//   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; see the file COPYING.  If not, write to
+//   the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+//   Boston, MA 02111-1307, USA.
+
+#include "download_thread.h"
+
+#include <vscreen/vscreen.h>
+
+#include <sigc++/bind.h>
+#include <sigc++/slot.h>
+#include <sigc++/functors/mem_fun.h>
+
+template<typename RVal>
+class background_execute : public vscreen_event
+{
+  sigc::slot0<RVal> slot;
+
+  threads::box<RVal> &return_box;
+public:
+  background_execute(const sigc::slot0<RVal> &_slot,
+		     threads::box<RVal> &_return_box)
+    :slot(_slot), return_box(_return_box)
+  {
+  }
+
+  void dispatch()
+  {
+    return_box.put(slot());
+  }
+};
+
+template<>
+class background_execute<void> : public vscreen_event
+{
+  sigc::slot0<void> slot;
+  threads::box<void> &return_box;
+public:
+  background_execute(const sigc::slot0<void> &_slot,
+		     threads::box<void> &_return_box)
+    :slot(_slot), return_box(_return_box)
+  {
+  }
+
+  void dispatch()
+  {
+    slot();
+    return_box.put();
+  }
+};
+
+/** Run the given function call in the foreground and return its value. */
+template<typename RVal>
+static
+RVal do_foreground_execute(pkgAcquireStatus *acq,
+			   RVal (pkgAcquireStatus::* fun) ())
+{
+  threads::box<RVal> return_box;
+
+  vscreen_post_event(new background_execute<RVal>(sigc::mem_fun(acq, fun),
+						  return_box));
+
+  return return_box.take();
+}
+
+/** Run the given function call in the foreground and return its value. */
+template<typename RVal, typename Arg0>
+static
+RVal do_foreground_execute(pkgAcquireStatus *acq,
+			   Arg0 arg0,
+			   RVal (pkgAcquireStatus::* fun) (Arg0))
+{
+  threads::box<RVal> return_box;
+
+  vscreen_post_event(new background_execute<RVal>(bind(sigc::mem_fun(acq, fun), arg0),
+						  return_box));
+
+  return return_box.take();
+}
+
+/** Run the given function call in the foreground and return its value. */
+template<typename RVal, typename Arg0, typename Arg1>
+static
+RVal do_foreground_execute(pkgAcquireStatus *acq,
+			   Arg0 arg0,
+			   Arg1 arg1,
+			   RVal (pkgAcquireStatus::* fun) (Arg0, Arg1))
+{
+  threads::box<RVal> return_box;
+
+  vscreen_post_event(new background_execute<RVal>(bind(sigc::mem_fun(acq, fun), arg0, arg1),
+						  return_box));
+
+  return return_box.take();
+}
+
+void background_status::Fetched(unsigned long Size,
+				unsigned long ResumePoint)
+{
+  do_foreground_execute(real_status, Size, ResumePoint, &pkgAcquireStatus::Fetched);
+}
+
+bool background_status::MediaChange(std::string Media, std::string Drive)
+{
+  return do_foreground_execute(real_status, Media, Drive, &pkgAcquireStatus::MediaChange);
+}
+
+void background_status::IMSHit(pkgAcquire::ItemDesc &item)
+{
+  do_foreground_execute<void, pkgAcquire::ItemDesc &>(real_status, item, &pkgAcquireStatus::IMSHit);
+}
+
+void background_status::Fetch(pkgAcquire::ItemDesc &item)
+{
+  do_foreground_execute<void, pkgAcquire::ItemDesc &>(real_status, item, &pkgAcquireStatus::Fetch);
+}
+
+void background_status::Done(pkgAcquire::ItemDesc &item)
+{
+  do_foreground_execute<void, pkgAcquire::ItemDesc &>(real_status, item, &pkgAcquireStatus::Done);
+}
+
+void background_status::Fail(pkgAcquire::ItemDesc &item)
+{
+  do_foreground_execute<void, pkgAcquire::ItemDesc &>(real_status, item, &pkgAcquireStatus::Fail);
+}
+
+bool background_status::Pulse(pkgAcquire *Owner)
+{
+  return do_foreground_execute(real_status, Owner, &pkgAcquireStatus::Pulse);
+}
+
+void background_status::Start()
+{
+  do_foreground_execute(real_status, &pkgAcquireStatus::Start);
+}
+
+void background_status::Stop()
+{
+  do_foreground_execute(real_status, &pkgAcquireStatus::Stop);
+}
+
+void download_thread::operator()()
+{
+  continuation(this, acq->Run());
+}

Added: branches/aptitude-0.3/aptitude/src/download_thread.h
==============================================================================
--- (empty file)
+++ branches/aptitude-0.3/aptitude/src/download_thread.h	Fri Sep  2 23:56:59 2005
@@ -0,0 +1,106 @@
+// download_thread                              -*-c++-*-
+//
+//   Copyright (C) 2005 Daniel Burrows
+//
+//   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; see the file COPYING.  If not, write to
+//   the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+//   Boston, MA 02111-1307, USA.
+
+#ifndef DOWNLOAD_THREAD_H
+#define DOWNLOAD_THREAD_H
+
+#include <apt-pkg/acquire.h>
+#include <apt-pkg/error.h>
+
+#include <generic/threads.h>
+
+#include <sigc++/slot.h>
+
+/** A proxy status object that posts messages to the main thread.
+ *  Each message "blocks" the download until the user deals with it,
+ *  just as if it was running in the main thread (I'm not sure
+ *  anything else is safe).
+ *
+ *  This object does NOT own the encapsulated status object and will
+ *  NOT delete it.
+ */
+class background_status : public pkgAcquireStatus
+{
+  pkgAcquireStatus *real_status;
+public:
+  virtual void Fetched(unsigned long Size, unsigned long ResumePoint);
+  virtual bool MediaChange(std::string Media, std::string Drive);
+  virtual void IMSHit(pkgAcquire::ItemDesc &);
+  virtual void Fetch(pkgAcquire::ItemDesc &);
+  virtual void Done(pkgAcquire::ItemDesc &);
+  virtual void Fail(pkgAcquire::ItemDesc &);
+  virtual bool Pulse(pkgAcquire *Owner);
+  virtual void Start();
+  virtual void Stop();
+
+  background_status(pkgAcquireStatus *_real_status)
+    :real_status(_real_status)
+  {
+  }
+};
+
+/** The thread that performs the download. */
+class download_thread
+{
+  threads::box<bool> cancelled;
+
+  /** The bundled pkgAcquire object.  It should have been initialized
+   *  using a background_status wrapper as above, and you should
+   *  join() this thread before deleting it.
+   */
+  pkgAcquire *acq;
+
+  /** The continuation of this download, called with this thread and
+   *  the result of the run as parameters.
+   */
+  sigc::slot2<void, download_thread *, pkgAcquire::RunResult> continuation;
+
+  threads::thread *t;
+
+  download_thread(const download_thread &other);
+  download_thread &operator=(const download_thread &other);
+public:
+  download_thread(pkgAcquire *_acq,
+		  const sigc::slot2<void, download_thread *, pkgAcquire::RunResult> &_continuation)
+    : cancelled(false), acq(_acq), continuation(_continuation), t(NULL)
+  {
+  }
+
+  ~download_thread()
+  {
+    delete t;
+  }
+
+  void operator()();
+
+  void start()
+  {
+    if(t != NULL)
+      _error->Error("Attempt to start a download thread twice!");
+    else
+      t = new threads::thread(threads::noncopy_bootstrap<download_thread>(*this));
+  }
+
+  void join()
+  {
+    t->join();
+  }
+};
+
+#endif // DOWNLOAD_THREAD_H



More information about the Aptitude-svn-commit mailing list