diff --git a/Frameworks/scm/src/scm.cc b/Frameworks/scm/src/scm.cc index 8b79c935..276170bb 100644 --- a/Frameworks/scm/src/scm.cc +++ b/Frameworks/scm/src/scm.cc @@ -1,6 +1,5 @@ #include "drivers/api.h" #include "scm.h" -#include "server.h" #include #include #include @@ -104,7 +103,6 @@ namespace scm _did_setup = true; } - status::type info_t::status (std::string const& path) { D(DBF_SCM, bug("%s\n", path.c_str());); @@ -142,17 +140,50 @@ namespace scm _callbacks.remove(cb); } + static bool test_and_set (std::string const& key, bool flag) + { + static dispatch_queue_t queue = dispatch_queue_create("org.textmate.scm.coordination", DISPATCH_QUEUE_SERIAL); + static std::set keys; + + __block bool foundKey = false; + dispatch_sync(queue, ^{ + auto it = keys.find(key); + foundKey = it != keys.end(); + if(flag && !foundKey) + keys.insert(key); + else if(!flag && foundKey) + keys.erase(it); + }); + return foundKey; + } + void info_t::callback (std::set const& pathsChangedOnDisk) { D(DBF_SCM, bug("( %s )\n", text::join(pathsChangedOnDisk, ", ").c_str());); - background_status(_wc_path, _driver, _updated, _snapshot, &update_status); - } - - void info_t::update_status (bool didUpdate, std::string const& path, fs::snapshot_t const& snapshot, scm::status_map_t const& newStatus) - { - if(!didUpdate) + if(test_and_set(_wc_path, true)) return; + static dispatch_queue_t queue = dispatch_queue_create("org.textmate.scm.status", DISPATCH_QUEUE_SERIAL); + dispatch_async(queue, ^{ + double elapsed = oak::date_t::now() - _updated; + if(elapsed < 3) + usleep((3 - elapsed) * 1000000); + + bool shouldCheck = _snapshot != fs::snapshot_t(_wc_path); + test_and_set(_wc_path, false); + if(shouldCheck) + { + scm::status_map_t status = _driver->status(_wc_path); + fs::snapshot_t snapshot(_wc_path); + dispatch_async(dispatch_get_main_queue(), ^{ + update_status(_wc_path, snapshot, status); + }); + } + }); + } + + void info_t::update_status (std::string const& path, fs::snapshot_t const& snapshot, scm::status_map_t const& newStatus) + { auto it = cache().find(path); if(it != cache().end()) { diff --git a/Frameworks/scm/src/scm.h b/Frameworks/scm/src/scm.h index 6ff1b656..50a7598f 100644 --- a/Frameworks/scm/src/scm.h +++ b/Frameworks/scm/src/scm.h @@ -53,7 +53,7 @@ namespace scm void callback (std::set const& pathsChangedOnDisk); oak::callbacks_t _callbacks; - static void update_status (bool didUpdate, std::string const& path, fs::snapshot_t const& snapshot, scm::status_map_t const& status); + static void update_status (std::string const& path, fs::snapshot_t const& snapshot, scm::status_map_t const& status); }; PUBLIC info_ptr info (std::string const& dir); diff --git a/Frameworks/scm/src/server.cc b/Frameworks/scm/src/server.cc deleted file mode 100644 index 2bff1ec6..00000000 --- a/Frameworks/scm/src/server.cc +++ /dev/null @@ -1,71 +0,0 @@ -#include "drivers/api.h" -#include "server.h" -#include -#include - -namespace -{ - struct payload_t - { - typedef payload_t* request_t; - - payload_t (std::string const& path, scm::driver_t const* driver, oak::date_t const& updated, fs::snapshot_t const& snapshot, void(*callback)(bool, std::string const&, fs::snapshot_t const&, scm::status_map_t const&)); - ~payload_t (); - - static bool handle_request (payload_t* request) - { - double elapsed = oak::date_t::now() - request->_updated; - if(elapsed < 3) - usleep((3 - elapsed) * 1000000); - - if(request->_snapshot == fs::snapshot_t(request->_path)) - return false; - - request->_status = request->_driver->status(request->_path); - request->_snapshot = fs::snapshot_t(request->_path); - request->_updated = oak::date_t::now(); - return true; - } - - void handle_reply (bool didUpdate) - { - _callback(didUpdate, _path, _snapshot, _status); - delete this; - } - - std::string const _path; - scm::driver_t const* _driver; - oak::date_t _updated; - fs::snapshot_t _snapshot; - scm::status_map_t _status; - - void(*_callback)(bool, std::string const&, fs::snapshot_t const&, scm::status_map_t const&); - size_t _client_key; - }; - - static oak::server_t& server () - { - static oak::server_t server; - return server; - } - - payload_t::payload_t (std::string const& path, scm::driver_t const* driver, oak::date_t const& updated, fs::snapshot_t const& snapshot, void(*callback)(bool, std::string const&, fs::snapshot_t const&, scm::status_map_t const&)) : _path(path), _driver(driver), _updated(updated), _snapshot(snapshot), _callback(callback) - { - _client_key = server().register_client(this); - server().send_request(_client_key, this); - } - - payload_t::~payload_t () - { - server().unregister_client(_client_key); - } -} - -namespace scm -{ - void background_status (std::string const& path, driver_t const* driver, oak::date_t const& updated, fs::snapshot_t const& snapshot, void(*callback)(bool, std::string const&, fs::snapshot_t const&, scm::status_map_t const&)) - { - new payload_t(path, driver, updated, snapshot, callback); - } - -} /* scm */ diff --git a/Frameworks/scm/src/server.h b/Frameworks/scm/src/server.h deleted file mode 100644 index 7a5fc98f..00000000 --- a/Frameworks/scm/src/server.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef SCM_SERVER_H_BND4Y51 -#define SCM_SERVER_H_BND4Y51 - -#include "snapshot.h" -#include "scm.h" -#include - -namespace scm -{ - PUBLIC void background_status (std::string const& path, driver_t const* driver, oak::date_t const& updated, fs::snapshot_t const& snapshot, void(*callback)(bool, std::string const&, fs::snapshot_t const&, scm::status_map_t const&)); - -} /* scm */ - -#endif /* end of include guard: SCM_SERVER_H_BND4Y51 */