1 Return-Path: <adrien@bustany.org>
\r
2 X-Original-To: notmuch@notmuchmail.org
\r
3 Delivered-To: notmuch@notmuchmail.org
\r
4 Received: from localhost (localhost [127.0.0.1])
\r
5 by olra.theworths.org (Postfix) with ESMTP id 677E7431FDE
\r
6 for <notmuch@notmuchmail.org>; Wed, 18 Jul 2012 11:41:09 -0700 (PDT)
\r
7 X-Virus-Scanned: Debian amavisd-new at olra.theworths.org
\r
11 X-Spam-Status: No, score=0 tagged_above=-999 required=5 tests=[none]
\r
13 Received: from olra.theworths.org ([127.0.0.1])
\r
14 by localhost (olra.theworths.org [127.0.0.1]) (amavisd-new, port 10024)
\r
15 with ESMTP id Fgysct7-kN8i for <notmuch@notmuchmail.org>;
\r
16 Wed, 18 Jul 2012 11:41:07 -0700 (PDT)
\r
17 Received: from mail.bustany.org (bustany.org [176.31.244.208])
\r
18 by olra.theworths.org (Postfix) with ESMTP id 81E4A431FC4
\r
19 for <notmuch@notmuchmail.org>; Wed, 18 Jul 2012 11:41:05 -0700 (PDT)
\r
20 Received: from localhost.localdomain (91-158-2-79.elisa-laajakaista.fi
\r
22 by mail.bustany.org (Postfix) with ESMTPSA id 6A6D91400C2
\r
23 for <notmuch@notmuchmail.org>; Wed, 18 Jul 2012 20:37:08 +0200 (CEST)
\r
24 From: Adrien Bustany <adrien@bustany.org>
\r
25 To: notmuch@notmuchmail.org
\r
26 Subject: [PATCH 3/7] go: Allow notmuch objects to be garbage collected
\r
27 Date: Wed, 18 Jul 2012 21:34:31 +0300
\r
28 Message-Id: <1342636475-16057-4-git-send-email-adrien@bustany.org>
\r
29 X-Mailer: git-send-email 1.7.7.6
\r
30 In-Reply-To: <1342636475-16057-1-git-send-email-adrien@bustany.org>
\r
31 References: <1342636475-16057-1-git-send-email-adrien@bustany.org>
\r
32 X-BeenThere: notmuch@notmuchmail.org
\r
33 X-Mailman-Version: 2.1.13
\r
35 List-Id: "Use and development of the notmuch mail system."
\r
36 <notmuch.notmuchmail.org>
\r
37 List-Unsubscribe: <http://notmuchmail.org/mailman/options/notmuch>,
\r
38 <mailto:notmuch-request@notmuchmail.org?subject=unsubscribe>
\r
39 List-Archive: <http://notmuchmail.org/pipermail/notmuch>
\r
40 List-Post: <mailto:notmuch@notmuchmail.org>
\r
41 List-Help: <mailto:notmuch-request@notmuchmail.org?subject=help>
\r
42 List-Subscribe: <http://notmuchmail.org/mailman/listinfo/notmuch>,
\r
43 <mailto:notmuch-request@notmuchmail.org?subject=subscribe>
\r
44 X-List-Received-Date: Wed, 18 Jul 2012 18:41:10 -0000
\r
46 This makes notmuch appropriately free the underlying notmuch C objects
\r
47 when garbage collecting their Go wrappers. To make sure we don't break
\r
48 the underlying links between objects (for example, a notmuch_messages_t
\r
49 being GC'ed before a notmuch_message_t belonging to it), we add for each
\r
50 wraper struct a pointer to the owner object (Go objects with a reference
\r
51 pointing to them don't get garbage collected).
\r
53 bindings/go/src/notmuch/notmuch.go | 153 +++++++++++++++++++++++++++++++-----
\r
54 1 files changed, 134 insertions(+), 19 deletions(-)
\r
56 diff --git a/bindings/go/src/notmuch/notmuch.go b/bindings/go/src/notmuch/notmuch.go
\r
57 index 1d77fd2..3f436a0 100644
\r
58 --- a/bindings/go/src/notmuch/notmuch.go
\r
59 +++ b/bindings/go/src/notmuch/notmuch.go
\r
60 @@ -11,6 +11,7 @@ package notmuch
\r
61 #include "notmuch.h"
\r
67 // Status codes used for the return values of most functions
\r
68 @@ -47,40 +48,152 @@ func (self Status) String() string {
\r
69 /* Various opaque data types. For each notmuch_<foo>_t see the various
\r
70 * notmuch_<foo> functions below. */
\r
72 +type Object interface {}
\r
74 type Database struct {
\r
75 db *C.notmuch_database_t
\r
78 +func createDatabase(db *C.notmuch_database_t) *Database {
\r
79 + self := &Database{db: db}
\r
81 + runtime.SetFinalizer(self, func(x *Database) {
\r
82 + if (x.db != nil) {
\r
83 + C.notmuch_database_destroy(x.db)
\r
91 query *C.notmuch_query_t
\r
95 +func createQuery(query *C.notmuch_query_t, owner Object) *Query {
\r
96 + self := &Query{query: query, owner: owner}
\r
98 + runtime.SetFinalizer(self, func(x *Query) {
\r
99 + if (x.query != nil) {
\r
100 + C.notmuch_query_destroy(x.query)
\r
107 type Threads struct {
\r
108 threads *C.notmuch_threads_t
\r
112 +func createThreads(threads *C.notmuch_threads_t, owner Object) *Threads {
\r
113 + self := &Threads{threads: threads, owner: owner}
\r
115 + runtime.SetFinalizer(self, func(x *Threads) {
\r
116 + if (x.threads != nil) {
\r
117 + C.notmuch_threads_destroy(x.threads)
\r
124 type Thread struct {
\r
125 thread *C.notmuch_thread_t
\r
129 +func createThread(thread *C.notmuch_thread_t, owner Object) *Thread {
\r
130 + self := &Thread{thread: thread, owner: owner}
\r
132 + runtime.SetFinalizer(self, func(x *Thread) {
\r
133 + if (x.thread != nil) {
\r
134 + C.notmuch_thread_destroy(x.thread)
\r
141 type Messages struct {
\r
142 messages *C.notmuch_messages_t
\r
146 +func createMessages(messages *C.notmuch_messages_t, owner Object) *Messages {
\r
147 + self := &Messages{messages: messages, owner: owner}
\r
152 type Message struct {
\r
153 message *C.notmuch_message_t
\r
157 +func createMessage(message *C.notmuch_message_t, owner Object) *Message {
\r
158 + self := &Message{message: message, owner: owner}
\r
160 + runtime.SetFinalizer(self, func(x *Message) {
\r
161 + if (x.message != nil) {
\r
162 + C.notmuch_message_destroy(x.message)
\r
170 tags *C.notmuch_tags_t
\r
174 +func createTags(tags *C.notmuch_tags_t, owner Object) *Tags {
\r
175 + self := &Tags{tags: tags, owner: owner}
\r
177 + runtime.SetFinalizer(self, func(x *Tags) {
\r
178 + if (x.tags != nil) {
\r
179 + C.notmuch_tags_destroy(x.tags)
\r
186 type Directory struct {
\r
187 dir *C.notmuch_directory_t
\r
191 +func createDirectory(directory *C.notmuch_directory_t, owner Object) *Directory {
\r
192 + self := &Directory{dir: directory, owner: owner}
\r
194 + runtime.SetFinalizer(self, func(x *Directory) {
\r
195 + if (x.dir != nil) {
\r
196 + C.notmuch_directory_destroy(x.dir)
\r
203 type Filenames struct {
\r
204 fnames *C.notmuch_filenames_t
\r
208 +func createFilenames(filenames *C.notmuch_filenames_t, owner Object) *Filenames {
\r
209 + self := &Filenames{fnames: filenames, owner: owner}
\r
211 + runtime.SetFinalizer(self, func(x *Filenames) {
\r
212 + if (x.fnames != nil) {
\r
213 + C.notmuch_filenames_destroy(x.fnames)
\r
220 type DatabaseMode C.notmuch_database_mode_t
\r
221 @@ -100,12 +213,13 @@ func NewDatabase(path string) (*Database, Status) {
\r
222 return nil, STATUS_OUT_OF_MEMORY
\r
225 - self := &Database{db: nil}
\r
226 - st := Status(C.notmuch_database_create(c_path, &self.db))
\r
227 + var db *C.notmuch_database_t;
\r
228 + st := Status(C.notmuch_database_create(c_path, &db))
\r
229 if st != STATUS_SUCCESS {
\r
234 + return createDatabase(db), st
\r
237 /* Open an existing notmuch database located at 'path'.
\r
238 @@ -134,12 +248,13 @@ func OpenDatabase(path string, mode DatabaseMode) (*Database, Status) {
\r
239 return nil, STATUS_OUT_OF_MEMORY
\r
242 - self := &Database{db: nil}
\r
243 - st := Status(C.notmuch_database_open(c_path, C.notmuch_database_mode_t(mode), &self.db))
\r
244 + var db *C.notmuch_database_t;
\r
245 + st := Status(C.notmuch_database_open(c_path, C.notmuch_database_mode_t(mode), &db))
\r
246 if st != STATUS_SUCCESS {
\r
251 + return createDatabase(db), st
\r
254 /* Close the given notmuch database, freeing all associated
\r
255 @@ -204,7 +319,7 @@ func (self *Database) GetDirectory(path string) (*Directory, Status) {
\r
256 if st != STATUS_SUCCESS || c_dir == nil {
\r
259 - return &Directory{dir: c_dir}, st
\r
260 + return createDirectory(c_dir, nil), st
\r
263 /* Add a new message to the given notmuch database.
\r
264 @@ -258,7 +373,7 @@ func (self *Database) AddMessage(fname string) (*Message, Status) {
\r
265 var c_msg *C.notmuch_message_t = new(C.notmuch_message_t)
\r
266 st := Status(C.notmuch_database_add_message(self.db, c_fname, &c_msg))
\r
268 - return &Message{message: c_msg}, st
\r
269 + return createMessage(c_msg, nil), st
\r
272 /* Remove a message from the given notmuch database.
\r
273 @@ -319,12 +434,12 @@ func (self *Database) FindMessage(message_id string) (*Message, Status) {
\r
274 return nil, STATUS_OUT_OF_MEMORY
\r
277 - msg := &Message{message: nil}
\r
278 - st := Status(C.notmuch_database_find_message(self.db, c_msg_id, &msg.message))
\r
279 + var msg *C.notmuch_message_t
\r
280 + st := Status(C.notmuch_database_find_message(self.db, c_msg_id, &msg))
\r
281 if st != STATUS_SUCCESS {
\r
285 + return createMessage(msg, nil), st
\r
288 /* Return a list of all tags found in the database.
\r
289 @@ -339,7 +454,7 @@ func (self *Database) GetAllTags() *Tags {
\r
293 - return &Tags{tags: tags}
\r
294 + return createTags(tags, nil)
\r
297 /* Create a new query for 'database'.
\r
298 @@ -379,7 +494,7 @@ func (self *Database) CreateQuery(query string) *Query {
\r
302 - return &Query{query: q}
\r
303 + return createQuery(q, nil)
\r
306 /* Sort values for notmuch_query_set_sort */
\r
307 @@ -459,7 +574,7 @@ func (self *Query) SearchThreads() *Threads {
\r
308 if threads == nil {
\r
311 - return &Threads{threads: threads}
\r
312 + return createThreads(threads, self)
\r
315 /* Execute a query for messages, returning a notmuch_messages_t object
\r
316 @@ -505,7 +620,7 @@ func (self *Query) SearchMessages() *Messages {
\r
320 - return &Messages{messages: msgs}
\r
321 + return createMessages(msgs, self)
\r
324 /* Destroy a notmuch_query_t along with any associated resources.
\r
325 @@ -607,7 +722,7 @@ func (self *Messages) Get() *Message {
\r
329 - return &Message{message: msg}
\r
330 + return createMessage(msg, self)
\r
333 /* Move the 'messages' iterator to the next message.
\r
334 @@ -659,7 +774,7 @@ func (self *Messages) CollectTags() *Tags {
\r
338 - return &Tags{tags: tags}
\r
339 + return createTags(tags, self)
\r
342 /* Get the message ID of 'message'.
\r
343 @@ -739,7 +854,7 @@ func (self *Message) GetReplies() *Messages {
\r
347 - return &Messages{messages: msgs}
\r
348 + return createMessages(msgs, self)
\r
351 /* Get a filename for the email corresponding to 'message'.
\r
352 @@ -871,7 +986,7 @@ func (self *Message) GetTags() *Tags {
\r
356 - return &Tags{tags: tags}
\r
357 + return createTags(tags, self)
\r
360 /* The longest possible tag value. */
\r