diff options
author | Michael Brown | 2007-05-15 18:53:46 +0200 |
---|---|---|
committer | Michael Brown | 2007-05-15 18:53:46 +0200 |
commit | b1755462ab344ff758c3a1e6ae0d10a729d96d1b (patch) | |
tree | 858bb7ba3d439be957f6b9530a0040b26c49f3f2 /src/core/downloader.c | |
parent | Data-transfer interface should now be functionally complete. (diff) | |
download | ipxe-b1755462ab344ff758c3a1e6ae0d10a729d96d1b.tar.gz ipxe-b1755462ab344ff758c3a1e6ae0d10a729d96d1b.tar.xz ipxe-b1755462ab344ff758c3a1e6ae0d10a729d96d1b.zip |
Do not hold self-references. This then avoids the problem of having to
ensure that we only drop our self-reference exactly once.
To maintain the guarantee that an object won't go out of scope
unexpectedly while one of its event handlers is being called, the
event-calling functions now automatically obtain and drop extra
references.
Diffstat (limited to 'src/core/downloader.c')
-rw-r--r-- | src/core/downloader.c | 22 |
1 files changed, 17 insertions, 5 deletions
diff --git a/src/core/downloader.c b/src/core/downloader.c index 2e466cbf..653a4806 100644 --- a/src/core/downloader.c +++ b/src/core/downloader.c @@ -51,6 +51,19 @@ struct downloader { }; /** + * Free downloader object + * + * @v refcnt Downloader reference counter + */ +static void downloader_free ( struct refcnt *refcnt ) { + struct downloader *downloader = + container_of ( refcnt, struct downloader, refcnt ); + + image_put ( downloader->image ); + free ( downloader ); +} + +/** * Terminate download * * @v downloader Downloader @@ -63,12 +76,8 @@ static void downloader_finished ( struct downloader *downloader, int rc ) { xfer_nullify ( &downloader->xfer ); /* Free resources and close interfaces */ - image_put ( downloader->image ); xfer_close ( &downloader->xfer, rc ); job_done ( &downloader->job, rc ); - - /* Drop reference to self */ - ref_put ( &downloader->refcnt ); } /** @@ -267,6 +276,7 @@ int create_downloader ( struct job_interface *job, const char *uri_string, if ( ! downloader ) return -ENOMEM; memset ( downloader, 0, sizeof ( *downloader ) ); + downloader->refcnt.free = downloader_free; job_init ( &downloader->job, &downloader_job_operations, &downloader->refcnt ); xfer_init ( &downloader->xfer, &downloader_xfer_operations, @@ -279,11 +289,13 @@ int create_downloader ( struct job_interface *job, const char *uri_string, uri_string ) ) != 0 ) goto err; - /* Attach parent interface and return */ + /* Attach parent interface, mortalise self, and return */ job_plug_plug ( &downloader->job, job ); + ref_put ( &downloader->refcnt ); return 0; err: downloader_finished ( downloader, rc ); + ref_put ( &downloader->refcnt ); return rc; } |