mirror of
https://github.com/textmate/textmate.git
synced 2026-01-22 05:07:54 -05:00
Use libdispatch for SCM status
Additionally the throttling has been improved. Previously we would delay a status fetch if it had been less than 3 seconds since the last request, but during this “penalty wait” more requests could still be submitted (in case of disk activity) and would be queued for later execution — now such requests are dropped.
This commit is contained in:
@@ -1,6 +1,5 @@
|
||||
#include "drivers/api.h"
|
||||
#include "scm.h"
|
||||
#include "server.h"
|
||||
#include <io/path.h>
|
||||
#include <cf/cf.h>
|
||||
#include <oak/oak.h>
|
||||
@@ -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<std::string> 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<std::string> 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())
|
||||
{
|
||||
|
||||
@@ -53,7 +53,7 @@ namespace scm
|
||||
void callback (std::set<std::string> const& pathsChangedOnDisk);
|
||||
oak::callbacks_t<callback_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);
|
||||
|
||||
@@ -1,71 +0,0 @@
|
||||
#include "drivers/api.h"
|
||||
#include "server.h"
|
||||
#include <io/path.h>
|
||||
#include <oak/server.h>
|
||||
|
||||
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<payload_t>& server ()
|
||||
{
|
||||
static oak::server_t<payload_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 */
|
||||
@@ -1,14 +0,0 @@
|
||||
#ifndef SCM_SERVER_H_BND4Y51
|
||||
#define SCM_SERVER_H_BND4Y51
|
||||
|
||||
#include "snapshot.h"
|
||||
#include "scm.h"
|
||||
#include <oak/misc.h>
|
||||
|
||||
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 */
|
||||
Reference in New Issue
Block a user