1 /* -*-C-*-
2 
3 Copyright (C) 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994,
4     1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
5     2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014 Massachusetts
6     Institute of Technology
7 
8 This file is part of MIT/GNU Scheme.
9 
10 MIT/GNU Scheme is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2 of the License, or (at
13 your option) any later version.
14 
15 MIT/GNU Scheme is distributed in the hope that it will be useful, but
16 WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18 General Public License for more details.
19 
20 You should have received a copy of the GNU General Public License
21 along with MIT/GNU Scheme; if not, write to the Free Software
22 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301,
23 USA.
24 
25 */
26 
27 #include "config.h"
28 #include "outf.h"
29 #include "dstack.h"
30 
31 static void error (const char *, const char *) NORETURN;
32 
33 static void
error(const char * procedure_name,const char * message)34 error (const char * procedure_name, const char * message)
35 {
36   outf_fatal ("%s: %s\n", procedure_name, message);
37   outf_flush_fatal ();
38   abort ();
39 }
40 
41 enum transaction_state { active, aborting, committing };
42 
43 struct transaction
44 {
45   void * checkpoint;
46   enum transaction_state state;
47 };
48 
49 static struct transaction * current_transaction;
50 
51 static void
guarantee_current_transaction(const char * proc)52 guarantee_current_transaction (const char * proc)
53 {
54   if (current_transaction == 0)
55     error (proc, "no transaction");
56   switch (current_transaction -> state)
57     {
58     case committing: error (proc, "commit in progress"); break;
59     case aborting: error (proc, "abort in progress"); break;
60     case active: break;
61     }
62 }
63 
64 void
transaction_initialize(void)65 transaction_initialize (void)
66 {
67   current_transaction = 0;
68 }
69 
70 void
transaction_begin(void)71 transaction_begin (void)
72 {
73   void * checkpoint = dstack_position;
74   struct transaction * transaction =
75     (dstack_alloc (sizeof (struct transaction)));
76   (transaction -> checkpoint) = checkpoint;
77   (transaction -> state) = active;
78   dstack_bind ((&current_transaction), transaction);
79 }
80 
81 void
transaction_abort(void)82 transaction_abort (void)
83 {
84   guarantee_current_transaction ("transaction_abort");
85   (current_transaction -> state) = aborting;
86   dstack_set_position (current_transaction -> checkpoint);
87 }
88 
89 void
transaction_commit(void)90 transaction_commit (void)
91 {
92   guarantee_current_transaction ("transaction_commit");
93   (current_transaction -> state) = committing;
94   dstack_set_position (current_transaction -> checkpoint);
95 }
96 
97 struct action
98 {
99   enum transaction_action_type type;
100   void (*procedure) (void * environment);
101   void * environment;
102 };
103 
104 static void
execute_action(void * action)105 execute_action (void * action)
106 {
107   if ((((struct action *) action) -> type) !=
108       (((current_transaction -> state) == committing)
109        ? tat_abort : tat_commit))
110     (* (((struct action *) action) -> procedure))
111       (((struct action *) action) -> environment);
112 }
113 
114 void
transaction_record_action(enum transaction_action_type type,void (* procedure)(void * environment),void * environment)115 transaction_record_action (enum transaction_action_type type,
116 			   void (*procedure) (void * environment),
117 			   void * environment)
118 {
119   guarantee_current_transaction ("transaction_record_action");
120   {
121     struct action * action = (dstack_alloc (sizeof (struct action)));
122     (action -> type) = type;
123     (action -> procedure) = procedure;
124     (action -> environment) = environment;
125     dstack_protect (execute_action, action);
126   }
127 }
128