Re: Библиотека коллекций с поддержкой commit()/rollback()
От: . Великобритания  
Дата: 21.12.14 13:17
Оценка: 10 (1)
Здравствуйте, andyag, Вы писали:

a> А не встречал ли кто библиотеку, реализующую коллекции с поддержкой транзакций? Причём не обязательно даже чтобы поддержка concurrency была. Хочется примерно вот такого:

Можно взять стек неизменяемых списков
import org.pcollections.PVector;
import org.pcollections.TreePVector;

import java.util.ArrayDeque;
import java.util.Deque;
import java.util.List;

public class TransactionalList<E>
{
    final Deque<PVector<E>> data = new ArrayDeque<>();

    public TransactionalList()
    {
        data.addFirst(TreePVector.<E>empty());
    }

    public void add(E e)
    {
        data.addFirst(data.removeFirst().plus(e));
    }

    public void begin()
    {
        data.addFirst(data.getFirst());
    }

    public void rollback()
    {
        data.removeFirst();
    }

    public void commit()
    {
        final PVector<E> newHead = data.removeFirst();
        data.removeFirst();//old head dropped
        data.addFirst(newHead);
    }

    public int size()
    {
        return data.getFirst().size();
    }

    public List<? extends E> data()
    {
        return data.getFirst();
    }
}

ну и юнит-тест
import org.junit.Test;

import static java.util.Arrays.asList;
import static org.junit.Assert.assertEquals;

public class TransactionalListTest
{
    @Test
    public void testAdd() throws Exception
    {
        TransactionalList<Integer> list = new TransactionalList<Integer>();
        list.begin();    // []
        list.begin();  // []
        list.add(1); // [1]
        assertEquals(1, list.size());
        assertEquals(asList(1), list.data());
        list.commit(); // [1]
        list.begin();  // [1]
        list.add(2); // [1, 2]
        assertEquals(asList(1, 2), list.data());
        assertEquals(2, list.size());
        list.commit(); // [1, 2]
        list.rollback(); // []
        assertEquals(0, list.size());
    }
}

С concurrency непонятно что делать. Ведь begin-commit из разных потоков пускать не получится. По-моему можно сделать только саму модификацию списка, через CAS делать замену вершины стека.
avalon/1.0.432
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.