aboutsummaryrefslogtreecommitdiffstats
path: root/src/location-corelocation.m
diff options
context:
space:
mode:
Diffstat (limited to 'src/location-corelocation.m')
-rw-r--r--src/location-corelocation.m122
1 files changed, 63 insertions, 59 deletions
diff --git a/src/location-corelocation.m b/src/location-corelocation.m
index 435697d..9f45899 100644
--- a/src/location-corelocation.m
+++ b/src/location-corelocation.m
@@ -22,14 +22,18 @@
#import <CoreLocation/CoreLocation.h>
+struct location_data {
+ struct location location;
+ int available;
+ int error;
+};
+
struct location_state {
NSThread *thread;
- NSLock *lock;
int pipe_fd_read;
int pipe_fd_write;
- int available;
- int error;
- struct location location;
+ struct location_data data;
+ struct location_data saved_data;
};
@@ -38,6 +42,14 @@ struct location_state {
@property (nonatomic) struct location_state *state;
@end
+
+static void
+send_data(struct location_state *state)
+{
+ while (write(state->pipe_fd_write, &state->data, sizeof(state->data)) == -1 && errno == EINTR);
+}
+
+
@implementation LocationDelegate;
- (void)start
@@ -62,20 +74,14 @@ struct location_state {
- (void)markError
{
- [self.state->lock lock];
- self.state->error = 1;
- [self.state->lock unlock];
-
- write(self.state->pipe_fd_write, "", 1);
+ self.state->data.error = 1;
+ send_data(self.state);
}
- (void)markUnavailable
{
- [self.state->lock lock];
- self.state->available = 0;
- [self.state->lock unlock];
-
- write(self.state->pipe_fd_write, "", 1);
+ self.state->data.available = 0;
+ send_data(self.state);
}
- (void)locationManager:(CLLocationManager *)manager
@@ -83,15 +89,10 @@ struct location_state {
{
CLLocation *newLocation = [locations firstObject];
- [self.state->lock lock];
-
- self.state->location.lat = newLocation.coordinate.latitude;
- self.state->location.lon = newLocation.coordinate.longitude;
- self.state->available = 1;
-
- [self.state->lock unlock];
-
- write(self.state->pipe_fd_write, "", 1);
+ self.state->data.location.lat = newLocation.coordinate.latitude;
+ self.state->data.location.lon = newLocation.coordinate.longitude;
+ self.state->data.available = 1;
+ send_data(self.state);
}
- (void)locationManager:(CLLocationManager *)manager
@@ -170,14 +171,14 @@ pipe_close_callback(CFFileDescriptorRef fdref, CFOptionFlags callBackTypes, void
static int
-location_corelocation_init(struct location_state **state)
+corelocation_create(struct location_state **state_out)
{
- *state = emalloc(sizeof(**state));
+ *state_out = emalloc(sizeof(**state_out));
return 0;
}
static int
-location_corelocation_start(struct location_state *state)
+corelocation_start(struct location_state *state)
{
LocationThread *thread;
int pipefds[2];
@@ -185,12 +186,13 @@ location_corelocation_start(struct location_state *state)
state->pipe_fd_read = -1;
state->pipe_fd_write = -1;
- state->available = 0;
- state->error = 0;
- state->location.lat = 0;
- state->location.lon = 0;
+ state->data.available = 0;
+ state->data.error = 0;
+ state->data.location.lat = 0;
+ state->data.location.lon = 0;
+ state->saved_data = state->data;
- if (pipe_nonblock(pipefds)) {
+ if (pipe_rdnonblock(pipefds)) {
weprintf(_("Failed to start CoreLocation provider!"));
return -1;
}
@@ -198,9 +200,7 @@ location_corelocation_start(struct location_state *state)
state->pipe_fd_read = pipefds[0];
state->pipe_fd_write = pipefds[1];
- write(state->pipe_fd_write, "", 1);
-
- state->lock = [[NSLock alloc] init];
+ send_data(state); /* TODO why? */
thread = [[LocationThread alloc] init];
thread.state = state;
@@ -211,7 +211,7 @@ location_corelocation_start(struct location_state *state)
}
static void
-location_corelocation_free(struct location_state *state)
+corelocation_free(struct location_state *state)
{
if (state->pipe_fd_read >= 0)
close(state->pipe_fd_read);
@@ -219,49 +219,53 @@ location_corelocation_free(struct location_state *state)
}
static void
-location_corelocation_print_help(FILE *f)
+corelocation_print_help(FILE *f)
{
fputs(_("Use the location as discovered by the Corelocation provider.\n"), f);
fputs("\n", f);
}
static int
-location_corelocation_set_option(struct location_state *state, const char *key, const char *value)
+corelocation_set_option(struct location_state *state, const char *key, const char *value)
{
+ (void) state;
+ (void) value;
weprintf(_("Unknown method parameter: `%s'."), key);
return -1;
}
static int
-location_corelocation_get_fd(struct location_state *state)
+corelocation_get_fd(struct location_state *state)
{
return state->pipe_fd_read;
}
static int
-location_corelocation_handle(struct location_state *state, location_t *location, int *available)
+corelocation_fetch(struct location_state *state, struct location *location_out, int *available_out)
{
- int error;
-
- read(state->pipe_fd_read, &(char){0}, 1);
-
- [state->lock lock];
- error = state->error;
- *location->lat = state->location;
- *available = state->available;
- [state->lock unlock];
+ struct location_data data;
+ ssize_t r;
+
+ for (;;) {
+ r = read(state->pipe_fd_read, &data, sizeof(data));
+ if (r == (ssize_t)sizeof(data)) {
+ state->saved_data = data;
+ } else if (r > 0) {
+ /* writes of 512 bytes or less are always atomic on pipes */
+ weprintf("read <pipe>: %s", _("Unexpected message size"));
+ } else if (!r || errno == EAGAIN) {
+ break;
+ } else if (errno != EINTR) {
+ weprintf("read <pipe>:");
+ state->saved_data.error = 1;
+ break;
+ }
+ }
- return error ? -1 : 0;
+ *location_out = state->saved_data.location;
+ *available_out = state->saved_data.available;
+ return state->saved_data.error ? -1 : 0;
}
-const location_provider_t corelocation_location_provider = {
- "corelocation",
- &location_corelocation_init,
- &location_corelocation_start,
- &location_corelocation_free,
- &location_corelocation_print_help,
- &location_corelocation_set_option,
- &location_corelocation_get_fd,
- &location_corelocation_handle
-};
+const location_provider_t corelocation_location_provider = LOCATION_PROVIDER_INIT("corelocation", corelocation);